/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  floatl.c
 *         \unit  floatl
 *        \brief  This is a simple large float number calculate module for C language
 *       \author  Lamdonn
 *      \version  v1.1.1
 *      \license  GPL-2.0
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#include "floatl.h"

/**
 * \brief A union for representing a single - precision floating - point number in different forms.
 * 
 * This union allows accessing a single - precision floating - point number (float) in three different ways:
 * 1. As a standard 'float' type.
 * 2. As an unsigned 32 - bit integer.
 * 3. As a structured representation with separate fields for the sign, exponent, and mantissa.
 */
typedef union {
    // Access the value as a standard single - precision floating - point number
    float float_;
    // Access the binary representation of the floating - point number as an unsigned 32 - bit integer
    uint32_t int_;
    // Access the individual components of the floating - point number (sign, exponent, mantissa)
    struct 
    {
        // The mantissa of the floating - point number, occupying 23 bits
        uint32_t mantissa : 23;
        // The exponent of the floating - point number, occupying 8 bits
        uint32_t exponent : 8;
        // The sign of the floating - point number, occupying 1 bit (0 for positive, 1 for negative)
        uint32_t sign : 1;
    };
} float_u;

/**
 * \brief A union for representing a double - precision floating - point number in different forms.
 * 
 * This union allows accessing a double - precision floating - point number (double) in three different ways:
 * 1. As a standard 'double' type.
 * 2. As a structure containing two 32 - bit unsigned integers (low and high parts).
 * 3. As a structured representation with separate fields for the sign, exponent, and mantissa.
 */
typedef union {
    // Access the value as a standard double - precision floating - point number
    double float_;
    // Access the binary representation of the floating - point number as two 32 - bit unsigned integers
    struct 
    {
        // The lower 32 bits of the binary representation
        uint32_t low;
        // The upper 32 bits of the binary representation
        uint32_t high;
    } int_;
    // Access the individual components of the floating - point number (sign, exponent, mantissa)
    struct 
    {
        // The lower part of the mantissa of the floating - point number
        uint32_t mantissa_l;
        // The upper 20 bits of the mantissa of the floating - point number
        uint32_t mantissa_h : 20;
        // The exponent of the floating - point number, occupying 11 bits
        uint32_t exponent : 11;
        // The sign of the floating - point number, occupying 1 bit (0 for positive, 1 for negative)
        uint32_t sign : 1;
    };
} double_u;

/**
 * \brief Definition of the 'floatl2' structure.
 * 
 * This structure is designed to represent a long - bit floating - point number in multiple ways.
 * It uses a union to provide different views of the same underlying data,
 * which can be accessed as arrays of 16 - bit or 32 - bit unsigned integers,
 * or as a combination of two 'floatl' structures.
 */
typedef struct {
    /**
     * \brief Union to provide different representations of the underlying data.
     * 
     * The union allows the data to be accessed in various formats:
     * as an array of 16 - bit unsigned integers, an array of 32 - bit unsigned integers,
     * or as two 'floatl' structures representing low and high parts.
     */
    union {
        /**
         * \brief Array of uint16_t values representing the long bit integer in 16 - bit segments.
         * 
         * This array can be used to access the underlying data in 16 - bit chunks.
         * The size of the array is determined by the macro __FLOATL2_U16_PARTS__.
         */
        uint16_t u16[__FLOATL2_U16_PARTS__];

        /**
         * \brief Array of uint32_t values representing the long bit integer in 32 - bit segments.
         * 
         * This array can be used to access the underlying data in 32 - bit chunks.
         * The size of the array is determined by the macro __FLOATL2_U32_PARTS__.
         */
        uint32_t u32[__FLOATL2_U32_PARTS__];

        /**
         * \brief Structured view with low and high 'floatl' components.
         * 
         * This struct divides the long - bit floating - point number into a low - order and a high - order 'floatl' part.
         */
        struct {
            /**
             * \brief The low - order 'floatl' part of the long - bit floating - point number.
             */
            floatl low;

            /**
             * \brief The high - order 'floatl' part of the long - bit floating - point number.
             */
            floatl high;
        };
    };
} floatl2;

/**
 * \brief Definition of the FL_STACK structure.
 * 
 * This structure represents a stack data structure. It contains information
 * about the stack's base address, capacity, current size, and the index of the stack tail.
 */
typedef struct
{
    /**
     * \brief Protected: base address of data.
     * 
     * This pointer points to the base address of the memory area where the stack data is stored.
     */
    char* base;

    /**
     * \brief Protected: capacity of stack.
     * 
     * It indicates the maximum number of elements that the stack can hold.
     */
    int capacity;

    /**
     * \brief Protected: size of stack.
     * 
     * This variable stores the current number of elements in the stack.
     */
    int size;

    /**
     * \brief Protected: index of stack tail.
     * 
     * It represents the index where the next element will be pushed or the last element was popped.
     */
    int tail;
} FL_STACK;

/**
 * \brief Macro to create a 'floatl2' structure with a given low - order part and a zero high - order part.
 * \param x: The value to be assigned to the 'low' member of the 'floatl2' structure.
 * \return A 'floatl2' structure with the 'low' member set to 'x' and the 'high' member set to '__FLOATL_INT_ZERO__'.
 * 
 * This macro simplifies the creation of a 'floatl2' structure by providing a convenient way to initialize
 * the 'low' member while setting the 'high' member to a predefined zero value.
 */
#define FLOATL2(x)                          (floatl2){.low=(x),.high=__FLOATL_INT_ZERO__}

/**
 * \brief Flag indicating zero - padding for formatted output.
 * 
 * When this flag is set, the output will be padded with zeros instead of spaces when the width is specified.
 */
#define FLAGS_ZEROPAD                       (0x01)

/**
 * \brief Flag indicating left - alignment for formatted output.
 * 
 * When this flag is set, the output will be left - aligned within the specified width.
 */
#define FLAGS_LEFT                          (0x02)

/**
 * \brief Flag indicating that a plus sign should be prepended to positive numbers in formatted output.
 * 
 * When this flag is set, positive numbers will be prefixed with a '+' sign.
 */
#define FLAGS_PLUS                          (0x04)

/**
 * \brief Flag indicating that a space should be prepended to positive numbers in formatted output.
 * 
 * When this flag is set, positive numbers will be prefixed with a space.
 */
#define FLAGS_SPACE                         (0x08)

/**
 * \brief Flag indicating the use of an alternate form for formatted output.
 * 
 * The exact meaning of the alternate form depends on the specific format specifier.
 */
#define FLAGS_HASH                          (0x10)

/**
 * \brief Flag indicating uppercase output for certain format specifiers.
 * 
 * When this flag is set, format specifiers that support case (e.g., 'a' vs 'A') will use the uppercase form.
 */
#define FLAGS_CASE                          (0x20)

/**
 * \brief Macro to print a character to the output buffer.
 * \param c: The character to be printed.
 * 
 * This macro checks if there is enough space in the buffer to store the character.
 * If there is, it adds the character to the buffer and increments the length.
 * If not, it returns - 2 to indicate that the buffer is too small.
 */
#define PRINT_CHAR(c)                       do { if (length < max) { buffer[length++] = (c); } else return -2; } while (0)

/**
 * \brief An array storing powers of 10 from 10^0 to 10^15 in 'floatl' format.
 * 
 * Each element in this array represents a power of 10, where the index corresponds to the exponent.
 * For example, flpow10[0] is 10^0, flpow10[1] is 10^1, and so on up to flpow10[15] which is 10^15.
 */
static floatl flpow10[16] = {
    FLOATL_CONST_1e0 ,  ///< Represents 10^0
    FLOATL_CONST_1e1 ,  ///< Represents 10^1
    FLOATL_CONST_1e2 ,  ///< Represents 10^2
    FLOATL_CONST_1e3 ,  ///< Represents 10^3
    FLOATL_CONST_1e4 ,  ///< Represents 10^4
    FLOATL_CONST_1e5 ,  ///< Represents 10^5
    FLOATL_CONST_1e6 ,  ///< Represents 10^6
    FLOATL_CONST_1e7 ,  ///< Represents 10^7
    FLOATL_CONST_1e8 ,  ///< Represents 10^8
    FLOATL_CONST_1e9 ,  ///< Represents 10^9
    FLOATL_CONST_1e10,  ///< Represents 10^10
    FLOATL_CONST_1e11,  ///< Represents 10^11
    FLOATL_CONST_1e12,  ///< Represents 10^12
    FLOATL_CONST_1e13,  ///< Represents 10^13
    FLOATL_CONST_1e14,  ///< Represents 10^14
    FLOATL_CONST_1e15,  ///< Represents 10^15
};

/* Internal static function declarations */

static int count_u32_leading_zero(uint32_t x);
static floatl floatl_pow10(int32_t n);
static char hexI(char c);
static int pad_mant(floatl *number, int *part, int *bitoffset, int *bitnum, char c);

static int floatl_int_ucmp(floatl a, floatl b);
static floatl floatl_int_umul(floatl a, floatl b);
static floatl floatl_int_udiv(floatl a, floatl b, floatl *mod);
static floatl floatl_int_umod(floatl a, floatl b);
static floatl floatl_int_add(floatl a, floatl b);
static floatl floatl_int_sub(floatl a, floatl b);
static floatl floatl_int_inc(floatl a);
static floatl floatl_int_dec(floatl a);
static floatl floatl_int_mul(floatl a, floatl b);
static floatl floatl_int_div(floatl a, floatl b);
static floatl floatl_int_mod(floatl a, floatl b);
static floatl floatl_int_shl(floatl a, uint32_t amount);
static floatl floatl_int_shr(floatl a, uint32_t amount);
static floatl floatl_int_and(floatl a, floatl b);
static floatl floatl_int_or(floatl a, floatl b);
static floatl floatl_int_xor(floatl a, floatl b);
static floatl floatl_int_not(floatl a);
static floatl floatl_int_abs(floatl a);
static int floatl_int_sign(floatl a);
static int floatl_int_cmp(floatl a, floatl b);
static floatl floatl_int_neg(floatl a);

static int floatl2_int_ucmp(floatl2 a, floatl2 b);
static floatl2 floatl2_int_shr(floatl2 a, uint32_t amount);
static floatl2 floatl2_int_shl(floatl2 a, uint32_t amount);
static int floatl2_int_sign(floatl2 a);
static floatl2 floatl2_int_add(floatl2 a, floatl2 b);
static floatl2 floatl2_int_sub(floatl2 a, floatl2 b);
static floatl2 floatl2_int_umul(floatl2 a, floatl2 b);
static floatl2 floatl2_int_udiv(floatl2 a, floatl2 b, floatl2 *mod);

/**
 * \brief Push a character onto the stack.
 * \param[in,out] st: Pointer to the FL_STACK structure.
 * \param[in] c: The character to be pushed onto the stack.
 * \return 1 if the push operation is successful, always returns 1 in this implementation.
 * 
 * This function adds a character to the stack. If the stack is not full, it increments the size.
 * It then updates the tail index in a circular manner.
 */
static int fl_stack_push(FL_STACK *st, char c)
{
    // Store the character at the current tail position
    st->base[st->tail] = c;
    // If the stack is not full, increment the size
    if (st->size < st->capacity) st->size++;
    // Update the tail index in a circular manner
    st->tail = (st->tail + 1) % st->capacity;
    return 1;
}

/**
 * \brief Pop a character from the stack.
 * \param[in,out] st: Pointer to the FL_STACK structure.
 * \param[out] c: Pointer to a character where the popped value will be stored.
 * \return 1 if the pop operation is successful, 0 if the stack is empty.
 * 
 * This function removes a character from the stack. It first checks if the stack is empty.
 * If not, it updates the tail index in a circular manner, retrieves the character, and decrements the size.
 */
static int fl_stack_pop(FL_STACK *st, char *c)
{
    // Check if the stack is empty
    if (st->size == 0) return 0;
    // Update the tail index in a circular manner to point to the last element
    st->tail = (st->tail + st->capacity - 1) % st->capacity;
    // Retrieve the character at the updated tail position
    *c = st->base[st->tail];
    // Decrement the size of the stack
    st->size--;
    return 1;
}

/**
 * \brief Push a character onto the stack from the head (a special push operation).
 * \param[in,out] st: Pointer to the FL_STACK structure.
 * \param[in] c: The character to be pushed onto the stack.
 * \return 1 if the push operation is successful, 0 if the stack is full.
 * 
 * This function adds a character to the stack from the "head" position.
 * It first checks if the stack is full. If not, it calculates the appropriate position
 * to insert the character and then increments the size.
 */
static int fl_stack_push_h(FL_STACK *st, char c)
{
    // Check if the stack is full
    if (st->size == st->capacity) return 0;
    // Calculate the position to insert the character from the head
    st->base[(st->tail - st->size + st->capacity - 1) % st->capacity] = c;
    // Increment the size of the stack
    st->size++;
    return 1;
}

/** 
 * \brief Adds two floatl numbers.
 * 
 * This function computes the sum of two 128-bit integers 
 * (floatl). It processes each 16-bit part of the input integers, 
 * handling carry bits as necessary. The result is stored in a 
 * new floatl number. This function ensures that overflow is 
 * correctly managed across all parts.
 * 
 * \param[in] a: The first operand (floatl number).
 * \param[in] b: The second operand (floatl number).
 * \return The sum of a and b as an floatl (128-bit integer).
 */
static floatl floatl_int_add(floatl a, floatl b) 
{
    floatl result; // Initialize the result variable
    uint16_t carry = 0; /** Carry bit */

    // Perform addition for each 16-bit part
    for (int i = 0; i < __FLOATL_U16_PARTS__; i++) 
    {
        // Calculate the sum of corresponding parts and carry
        uint32_t sum = (uint32_t)a.u16[i] + (uint32_t)b.u16[i] + carry;
        result.u16[i] = (uint16_t)(sum & 0xFFFF); /** Lower 16 bits */
        carry = (sum >> 16) & 0xFFFF; /** Upper 16 bits as carry */
    }

    return result; // Return the resulting floatl number
}

/** 
 * \brief Subtracts one floatl number from another.
 * 
 * This function computes the difference of two 128-bit integers 
 * (floatl). It processes each 16-bit part of the minuend and 
 * subtrahend, handling borrow bits as necessary. The result is 
 * stored in a new floatl number. This function ensures that 
 * borrowing is correctly managed across all parts.
 * 
 * \param[in] a: The minuend (the number from which another is to be subtracted).
 * \param[in] b: The subtrahend (the number to be subtracted).
 * \return The result of a - b as an floatl (128-bit integer).
 */
static floatl floatl_int_sub(floatl a, floatl b) 
{
    floatl result; // Initialize the result variable

    // Perform subtraction for each 16-bit part
    for (int i = 0; i < __FLOATL_U16_PARTS__; i++) 
    {
        uint32_t diff = (uint32_t)a.u16[i] - (uint32_t)b.u16[i];
        
        // Check if a borrow occurred
        if (diff & 0xFFFF0000) /** Borrow occurred */
        {
            // Adjust the higher parts to account for the borrow
            for (int j = i + 1; j < __FLOATL_U16_PARTS__; j++) 
            {
                a.u16[j] -= 1; // Borrow from the next part
                if (a.u16[j] != 0xFFFF) break; // Stop if no further borrow needed
            }
        }
        
        // Store the result of the subtraction
        result.u16[i] = (uint16_t)(diff & 0xFFFF);
    }

    return result; // Return the resulting floatl number
}

/** 
 * \brief Increments the floatl number by one.
 * 
 * This function increments a 128-bit integer (floatl) by one. 
 * It processes each 32-bit part of the input integer and 
 * handles carry bits as necessary. The function continues 
 * to increment the subsequent parts until there is no overflow.
 * 
 * \param[in] a: The floatl number to increment.
 * \return The incremented floatl number as an floatl (128-bit integer).
 */
static floatl floatl_int_inc(floatl a) 
{
    // Increment each 32-bit part of the floatl number
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        a.u32[i]++; // Increment the current part
        // Check if the current part overflowed
        if (a.u32[i] != 0) 
        {
            break; /** Return immediately if no overflow */
        }
    }
    return a; /** Return the incremented result */
}

/** 
 * \brief Decrements the floatl number by one.
 * 
 * This function decrements a 128-bit integer (floatl) by one. 
 * It processes each 32-bit part of the input integer, handling 
 * borrowing as necessary. If the current part is zero, it sets 
 * that part to its maximum value (0xFFFFFFFF) and continues 
 * to the next part to borrow from it.
 * 
 * \param[in] a: The floatl number to decrement.
 * \return The decremented floatl number as an floatl (128-bit integer).
 */
static floatl floatl_int_dec(floatl a) 
{
    // Decrement each 32-bit part of the floatl number
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        // Check if the current part can be decremented
        if (a.u32[i] != 0) 
        {
            a.u32[i]--; // Decrement the current part
            break; /** Return immediately if current part can be decremented */
        }
        // If current part is zero, set it to max value and continue borrowing
        a.u32[i] = 0xFFFFFFFF; 
    }
    return a; /** Return the decremented result */
}

/** 
 * \brief Multiplies two floatl unsigned numbers.
 * 
 * This function performs multiplication of two 128-bit unsigned integers 
 * (floatl) by using a method similar to the schoolbook algorithm. The 
 * multiplication is carried out by breaking the numbers into their 
 * 16-bit components and accumulating the results. The function handles 
 * carry-over during the multiplication and addition stages to ensure 
 * the final product is accurately represented.
 * 
 * \param[in] a: The first operand to multiply.
 * \param[in] b: The second operand to multiply.
 * \return The product of a and b as an floatl (128-bit unsigned integer).
 */
static floatl floatl_int_umul(floatl a, floatl b) 
{
    floatl result = {0}; /** Initialize the result to 0 */
    floatl temp[__FLOATL_U16_PARTS__] = {{0}}; // Temporary storage for intermediate results
    uint16_t carry = 0; // Variable to hold carry-over during multiplication

    // Perform multiplication
    for (int i = 0; i < __FLOATL_U16_PARTS__; i++) 
    {
        carry = 0; // Reset carry for the current row
        for (int j = 0; j < __FLOATL_U16_PARTS__; j++) 
        {
            if (i + j < __FLOATL_U16_PARTS__) 
            {
                // Multiply the 16-bit segments and add carry
                uint32_t mul = (uint32_t)a.u16[i] * (uint32_t)b.u16[j] + carry;
                temp[i].u16[i + j] = (mul & 0xFFFF); // Store the lower 16 bits
                carry = ((mul >> 16) & 0xFFFF); // Update carry for the next addition
            }
        }
    }

    carry = 0; // Reset carry for the addition phase
    // Combine results from the temporary storage
    for (int i = 0; i < __FLOATL_U16_PARTS__; i++) 
    {
        uint32_t add = 0; // Variable to hold the sum of the current column
        for (int j = 0; j < __FLOATL_U16_PARTS__; j++) 
        {
            add += temp[j].u16[i]; // Accumulate results from temp
        }
        add += carry; // Add any carry from the previous column
        result.u16[i] = (add & 0xFFFF); // Store the lower 16 bits in result
        carry = ((add >> 16) & 0xFFFF); // Update carry for the next column
    }

    return result; // Return the final product
}

/** 
 * \brief Multiplies two floatl numbers.
 * 
 * This function multiplies two 128-bit integers (floatl) and returns 
 * the product as another floatl number. It handles signed multiplication 
 * by checking the sign of the operands. If either operand is negative, 
 * it negates the operand and adjusts the sign of the result accordingly. 
 * The actual multiplication is performed using the `floatl_int_umul` 
 * function, which handles the absolute values of the integers.
 * 
 * \param[in] a: The first operand to multiply.
 * \param[in] b: The second operand to multiply.
 * \return The product of a and b as an floatl (128-bit integer).
 */
static floatl floatl_int_mul(floatl a, floatl b)
{
    floatl result = {0}; // Initialize the result to 0
    int sign = 1; // Variable to track the sign of the result

    // Check and handle the sign of the first operand
    if (a.u32[__FLOATL_U32_PARTS__ - 1] & 0x80000000)
    {
        sign = -sign; // Negate the sign for the result
        a = floatl_int_neg(a); // Negate the first operand
    }

    // Check and handle the sign of the second operand
    if (b.u32[__FLOATL_U32_PARTS__ - 1] & 0x80000000)
    {
        sign = -sign; // Negate the sign for the result
        b = floatl_int_neg(b); // Negate the second operand
    }

    // Perform unsigned multiplication
    result = floatl_int_umul(a, b);
    
    // If the result should be negative, negate it
    if (sign < 0) 
        result = floatl_int_neg(result);
    
    return result; // Return the final product
}

/** 
 * \brief Divides one floatl unsigned number by another.
 * 
 * This function performs division of one 128-bit unsigned integer (floatl) 
 * by another. It calculates the quotient using a bitwise approach, 
 * handling division by zero gracefully. The result is built bit by bit 
 * from the most significant bit to the least significant bit. If the 
 * divisor is zero, it prints an error message and returns zero.
 * 
 * \param[in] a: The dividend (number to be divided).
 * \param[in] b: The divisor (number to divide by).
 * \return The quotient of a divided by b as an floatl (128-bit unsigned integer).
 */
static floatl floatl_int_udiv(floatl a, floatl b, floatl *mod)  
{
    // Check for division by zero
    if (floatl_int_sign(b) == 0)
    {
        printf("Division by zero!\n");
        return (floatl){0}; /** Handle division by zero */
    }

    floatl result = {0};      // Initialize the result to zero
    floatl remainder = {0};   // Initialize the remainder to zero

    /** Calculate bit by bit from the highest bit */
    for (int i = __FLOATL_BIT_PARTS__ - 1; i >= 0; i--) 
    {
        /** Left shift remainder and add current bit */
        remainder = floatl_int_shl(remainder, 1); // Shift remainder left by 1
        remainder.u32[0] |= (a.u32[i / 32] >> (i % 32)) & 1; // Add current bit from dividend

        /** If remainder is greater than or equal to b, subtract b */
        if (floatl_int_ucmp(remainder, b) >= 0) 
        {
            remainder = floatl_int_sub(remainder, b); // Subtract b from remainder
            result.u32[i / 32] |= (1 << (i % 32)); // Set corresponding bit in result
        }
    }

    if (mod) *mod = remainder;

    return result; // Return the final quotient
}

/** 
 * \brief Divides one floatl number by another.
 * 
 * This function performs division of two 128-bit integers (floatl) 
 * and returns the quotient as another floatl number. It handles signed 
 * division by checking the sign of the operands. If either operand 
 * is negative, it negates the operand and adjusts the sign of the 
 * result accordingly. The actual division is performed using the 
 * `floatl_int_udiv` function, which handles the absolute values of 
 * the integers.
 * 
 * \param[in] a: The dividend (number to be divided).
 * \param[in] b: The divisor (number to divide by).
 * \return The quotient of a divided by b as an floatl (128-bit integer).
 */
static floatl floatl_int_div(floatl a, floatl b)
{
    floatl result = {0}; // Initialize the result to 0
    int sign = 1; // Variable to track the sign of the result

    // Check and handle the sign of the dividend
    if (a.u32[__FLOATL_U32_PARTS__ - 1] & 0x80000000)
    {
        sign = -sign; // Negate the sign for the result
        a = floatl_int_neg(a); // Negate the dividend
    }

    // Check and handle the sign of the divisor
    if (b.u32[__FLOATL_U32_PARTS__ - 1] & 0x80000000)
    {
        sign = -sign; // Negate the sign for the result
        b = floatl_int_neg(b); // Negate the divisor
    }

    // Perform unsigned division
    result = floatl_int_udiv(a, b, NULL);

    // If the result should be negative, negate it
    if (sign < 0) 
        result = floatl_int_neg(result);
    
    return result; // Return the final quotient
}

/** 
 * \brief Computes the remainder of the division of two unsigned floatl numbers.
 * 
 * This function calculates the remainder of the division of two 
 * 128-bit unsigned integers (floatl). It uses a bitwise approach to 
 * compute the remainder by processing each bit from the most significant 
 * to the least significant. If the divisor is zero, it handles the 
 * error gracefully by printing a message and returning zero.
 * 
 * \param[in] a: The dividend (number to be divided).
 * \param[in] b: The divisor (number to divide by).
 * \return The remainder of a divided by b as an floatl (128-bit unsigned integer).
 */
static floatl floatl_int_umod(floatl a, floatl b) 
{
    floatl mod = {0};
    floatl_int_udiv(a, b, &mod);
    return mod;
}

/** 
 * \brief Computes the remainder of the division of two floatl numbers.
 * 
 * This function calculates the remainder of the division of two 
 * 128-bit integers (floatl). It handles signed integers by checking 
 * the sign of the dividend. If the dividend is negative, it negates 
 * the dividend before performing the unsigned modulus operation. 
 * The sign of the result is adjusted based on the sign of the 
 * dividend. The actual remainder calculation is performed using the 
 * `floatl_int_umod` function, which handles the absolute values of 
 * the integers.
 * 
 * \param[in] a: The dividend (number to be divided).
 * \param[in] b: The divisor (number to divide by).
 * \return The remainder of a divided by b as an floatl (128-bit integer).
 */
static floatl floatl_int_mod(floatl a, floatl b)
{
    floatl result = {0}; // Initialize result to zero
    int sign = 1; // Variable to track the sign of the result

    // Check and handle the sign of the dividend
    if (a.u32[__FLOATL_U32_PARTS__ - 1] & 0x80000000)
    {
        sign = -sign; // Negate the sign for the result
        a = floatl_int_neg(a); // Negate the dividend
    }

    // Perform unsigned modulus with the absolute value of the divisor
    result = floatl_int_umod(a, floatl_int_abs(b));

    // If the result should be negative, negate it
    if (sign < 0) 
        result = floatl_int_neg(result);
    
    return result; // Return the final remainder
}

/** 
 * \brief Left shifts an floatl number by a specified number of bits.
 * 
 * This function performs a left bitwise shift on a 128-bit integer 
 * (floatl). The shift amount can be greater than 32 bits, in which case 
 * the function calculates how many whole 32-bit parts to shift and 
 * how many bits to shift within the remaining part. It constructs 
 * the result based on the input number after applying the shift.
 * 
 * \param[in] a: The floatl number to shift.
 * \param[in] amount: The number of bits to shift to the left.
 * \return The left-shifted floatl number.
 */
static floatl floatl_int_shl(floatl a, uint32_t amount) 
{
    floatl result = {0}; // Initialize the result to zero
    int u32bias = amount / 32; // Number of whole 32-bit parts to shift
    int bitsbias = amount % 32; // Remaining bits to shift

    // Perform the shift for each 32-bit part of the floatl number
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        if (i < u32bias)
        {
            result.u32[i] = 0; // Set shifted-out parts to zero
        }
        else 
        {
            // Shift the current part and add bits from the previous part if needed
            result.u32[i] = (a.u32[i - u32bias] << bitsbias) | 
                (((i - u32bias - 1) >= 0 && bitsbias > 0) ? 
                (a.u32[i - u32bias - 1] >> (32 - bitsbias)) : 0);
        }
    }
    return result; // Return the left-shifted result
}

/** 
 * \brief Right shifts an floatl number by a specified number of bits.
 * 
 * This function performs a right bitwise shift on a 128-bit integer 
 * (floatl). The shift amount can be greater than 32 bits, in which case 
 * the function calculates how many whole 32-bit parts to shift and 
 * how many bits to shift within the remaining part. It constructs 
 * the result based on the input number after applying the shift. 
 * The sign bit is preserved for signed shifts.
 * 
 * \param[in] a: The floatl number to shift.
 * \param[in] amount: The number of bits to shift to the right.
 * \return The right-shifted floatl number.
 */
static floatl floatl_int_shr(floatl a, uint32_t amount) 
{
    floatl result = {0}; // Initialize the result to zero
    int u32bias = amount / 32; // Number of whole 32-bit parts to shift
    int bitsbias = amount % 32; // Remaining bits to shift

    // Perform the shift for each 32-bit part of the floatl number
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        // Check if the current index is beyond the range for valid shifts
        if (i > __FLOATL_U32_PARTS__ - u32bias - 1 && __FLOATL_U32_PARTS__ - u32bias - 1 >= 0)
        {
            result.u32[i] = 0; // Set shifted-out parts to zero
        }
        else 
        {
            // Shift the current part and add bits from the next part if needed
            result.u32[i] = (a.u32[i + u32bias] >> bitsbias) | 
                (((i + u32bias + 1) < __FLOATL_U32_PARTS__ && bitsbias > 0) ? 
                (a.u32[i + u32bias + 1] << (32 - bitsbias)) : 
                ((a.u32[__FLOATL_U32_PARTS__ - 1] & 0x80000000) ? 0xFFFFFFFF : 0));
        }
    }

    return result; // Return the right-shifted result
}

/** 
 * \brief Performs bitwise AND operation on two floatl numbers.
 * 
 * This function computes the bitwise AND of two 128-bit integers 
 * (floatl). It processes each 32-bit part of the input integers and 
 * performs the AND operation on corresponding parts, storing the 
 * result in a new floatl number. This operation yields a number that 
 * has bits set only where both operands have bits set.
 * 
 * \param[in] a: The first operand (floatl number).
 * \param[in] b: The second operand (floatl number).
 * \return The result of a AND b as an floatl (128-bit integer).
 */
static floatl floatl_int_and(floatl a, floatl b) 
{
    floatl result; // Initialize the result variable
    // Perform the bitwise AND operation for each 32-bit part
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        result.u32[i] = a.u32[i] & b.u32[i]; // Compute AND for each part
    }
    return result; // Return the resulting floatl number
}

/** 
 * \brief Performs bitwise OR operation on two floatl numbers.
 * 
 * This function computes the bitwise OR of two 128-bit integers 
 * (floatl). It processes each 32-bit part of the input integers and 
 * performs the OR operation on corresponding parts, storing the 
 * result in a new floatl number. This operation yields a number that 
 * has bits set where at least one of the operands has bits set.
 * 
 * \param[in] a: The first operand (floatl number).
 * \param[in] b: The second operand (floatl number).
 * \return The result of a OR b as an floatl (128-bit integer).
 */
static floatl floatl_int_or(floatl a, floatl b) 
{
    floatl result; // Initialize the result variable
    // Perform the bitwise OR operation for each 32-bit part
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        result.u32[i] = a.u32[i] | b.u32[i]; // Compute OR for each part
    }
    return result; // Return the resulting floatl number
}

/** 
 * \brief Performs bitwise XOR operation on two floatl numbers.
 * 
 * This function computes the bitwise XOR of two 128-bit integers 
 * (floatl). It processes each 32-bit part of the input integers and 
 * performs the XOR operation on corresponding parts, storing the 
 * result in a new floatl number. This operation yields a number that 
 * has bits set where only one of the operands has bits set.
 * 
 * \param[in] a: The first operand (floatl number).
 * \param[in] b: The second operand (floatl number).
 * \return The result of a XOR b as an floatl (128-bit integer).
 */
static floatl floatl_int_xor(floatl a, floatl b) 
{
    floatl result; // Initialize the result variable
    // Perform the bitwise XOR operation for each 32-bit part
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        result.u32[i] = a.u32[i] ^ b.u32[i]; // Compute XOR for each part
    }
    return result; // Return the resulting floatl number
}

/** 
 * \brief Performs bitwise NOT operation on an floatl number.
 * 
 * This function computes the bitwise NOT (negation) of a 128-bit 
 * integer (floatl). It processes each 32-bit part of the input integer 
 * and applies the NOT operation, storing the result in a new floatl 
 * number. This operation inverts all bits of the input number.
 * 
 * \param[in] a: The floatl number to negate.
 * \return The bitwise negation of a as an floatl (128-bit integer).
 */
static floatl floatl_int_not(floatl a) 
{
    floatl result; // Initialize the result variable
    // Perform the bitwise NOT operation for each 32-bit part
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        result.u32[i] = ~a.u32[i]; // Compute NOT for each part
    }
    return result; // Return the resulting floatl number
}

/** 
 * \brief Computes the absolute value of an floatl number.
 * 
 * This function checks if the given 128-bit unsigned integer (floatl) 
 * represents a negative value in two's complement representation. 
 * If the most significant bit (sign bit) of the highest 32-bit segment 
 * is set, it indicates a negative number, and the function calls 
 * floatl_int_neg to return its positive equivalent. If the number is 
 * already non-negative, it simply returns the original number.
 * 
 * \param[in] a: The floatl number for which to compute the absolute value.
 * \return The absolute value of the floatl number a.
 */
static floatl floatl_int_abs(floatl a) 
{
    // Check if the sign bit of the highest 32-bit part is set
    if (a.u32[__FLOATL_U32_PARTS__ - 1] & 0x80000000) 
        return floatl_int_neg(a); // Return negated value if negative
    return a; // Return the original value if non-negative
}

/** 
 * \brief Determines the sign of an floatl number.
 * 
 * This function checks the sign of the given 128-bit unsigned integer 
 * (floatl) based on its representation. It first examines the most significant 
 * bit of the highest 32-bit segment to determine if the number is negative. 
 * If this bit is set, the function returns -1, indicating a negative value. 
 * If all segments are zero, it returns 0, indicating that the number is zero. 
 * If the number is positive, it returns 1.
 * 
 * \param[in] a: The floatl number to evaluate for its sign.
 * \return -1 if the number is negative, 0 if the number is zero, and 
 *         1 if the number is positive.
 */
static int floatl_int_sign(floatl a)
{
    // Check if the sign bit of the highest 32-bit part is set
    if (a.u32[__FLOATL_U32_PARTS__ - 1] & 0x80000000) return -1;

    // Check if the number is zero
    for (int i = __FLOATL_U32_PARTS__ - 1; i >= 0; i--) 
    {
        if (a.u32[i] != 0) return 1; // Return 1 if any part is non-zero
    }
    
    return 0; // Return 0 if all parts are zero
}

/** 
 * \brief Compares two floatl unsigned numbers.
 * 
 * This function compares two 128-bit unsigned integers (floatl) 
 * by examining each 32-bit segment from the most significant to 
 * the least significant. It returns 1 if the first number is 
 * greater than the second, -1 if it is less, and 0 if they are 
 * equal. The comparison is done in a way that respects the 
 * unsigned nature of the integers.
 * 
 * \param[in] a: The first number to compare.
 * \param[in] b: The second number to compare.
 * \return 1 if a > b, -1 if a < b, and 0 if a == b.
 */
static int floatl_int_ucmp(floatl a, floatl b) 
{
    // Compare each 32-bit part from the most significant to the least significant
    for (int i = __FLOATL_U32_PARTS__ - 1; i >= 0; i--) 
    {
        if (a.u32[i] > b.u32[i]) return 1;  // a is greater
        if (a.u32[i] < b.u32[i]) return -1; // a is less
    }
    return 0; // a and b are equal
}

/** 
 * \brief Compares two floatl numbers.
 * 
 * This function compares two 128-bit integers (floatl) and 
 * determines their relative order. The comparison is performed 
 * starting from the most significant part (highest order) to 
 * the least significant part (lowest order).
 * 
 * \param[in] a: The first number to compare.
 * \param[in] b: The second number to compare.
 * 
 * \return 1 if a > b, -1 if a < b, 0 if a == b.
 */
static int floatl_int_cmp(floatl a, floatl b) 
{
    // Compare each 32-bit part from the most significant to the least significant
    for (int i = __FLOATL_U32_PARTS__ - 1; i >= 0; i--) 
    {
        // Compare the current parts as signed integers
        if ((int32_t)a.u32[i] > (int32_t)b.u32[i]) return 1; // a is greater
        if ((int32_t)a.u32[i] < (int32_t)b.u32[i]) return -1; // a is less
    }
    return 0; // a is equal to b
}

/** 
 * \brief Computes the two's complement (negation) of an floatl number.
 * 
 * This function calculates the negative representation of a given 128-bit 
 * unsigned integer (floatl) using two's complement. It first inverts all bits 
 * of the input number and then adds one to the result. This effectively 
 * represents the negative value of the original number in a signed 
 * integer format.
 * 
 * \param[in] a: The floatl number to negate.
 * \return The negated floatl number (two's complement of a).
 */
static floatl floatl_int_neg(floatl a)
{
    floatl result = {0};

    // First, bitwise NOT (invert) the input number
    for (int i = 0; i < __FLOATL_U32_PARTS__; i++) 
    {
        result.u32[i] = ~a.u32[i];
    }

    // Add one to complete the two's complement operation
    return floatl_int_inc(result);
}

/** 
 * \brief Compares two floatl unsigned numbers.
 * 
 * This function compares two 128-bit unsigned integers (floatl) 
 * by examining each 32-bit segment from the most significant to 
 * the least significant. It returns 1 if the first number is 
 * greater than the second, -1 if it is less, and 0 if they are 
 * equal. The comparison is done in a way that respects the 
 * unsigned nature of the integers.
 * 
 * \param[in] a: The first number to compare.
 * \param[in] b: The second number to compare.
 * \return 1 if a > b, -1 if a < b, and 0 if a == b.
 */
static int floatl2_int_ucmp(floatl2 a, floatl2 b) 
{
    // Compare each 32-bit part from the most significant to the least significant
    for (int i = __FLOATL2_U32_PARTS__ - 1; i >= 0; i--) 
    {
        if (a.u32[i] > b.u32[i]) return 1;  // a is greater
        if (a.u32[i] < b.u32[i]) return -1; // a is less
    }
    return 0; // a and b are equal
}

/** 
 * \brief Right shifts an floatl number by a specified number of bits.
 * 
 * This function performs a right bitwise shift on a 128-bit integer 
 * (floatl). The shift amount can be greater than 32 bits, in which case 
 * the function calculates how many whole 32-bit parts to shift and 
 * how many bits to shift within the remaining part. It constructs 
 * the result based on the input number after applying the shift. 
 * The sign bit is preserved for signed shifts.
 * 
 * \param[in] a: The floatl number to shift.
 * \param[in] amount: The number of bits to shift to the right.
 * \return The right-shifted floatl number.
 */
static floatl2 floatl2_int_shr(floatl2 a, uint32_t amount) 
{
    floatl2 result = {0}; // Initialize the result to zero
    int u32bias = amount / 32; // Number of whole 32-bit parts to shift
    int bitsbias = amount % 32; // Remaining bits to shift

    // Perform the shift for each 32-bit part of the floatl number
    for (int i = 0; i < __FLOATL2_U32_PARTS__; i++) 
    {
        // Check if the current index is beyond the range for valid shifts
        if (i > __FLOATL2_U32_PARTS__ - u32bias - 1 && __FLOATL2_U32_PARTS__ - u32bias - 1 >= 0)
        {
            result.u32[i] = 0; // Set shifted-out parts to zero
        }
        else 
        {
            // Shift the current part and add bits from the next part if needed
            result.u32[i] = (a.u32[i + u32bias] >> bitsbias) | 
                (((i + u32bias + 1) < __FLOATL2_U32_PARTS__ && bitsbias > 0) ? 
                (a.u32[i + u32bias + 1] << (32 - bitsbias)) : 
                ((a.u32[__FLOATL2_U32_PARTS__ - 1] & 0x80000000) ? 0xFFFFFFFF : 0));
        }
    }

    return result; // Return the right-shifted result
}

/** 
 * \brief Left shifts an floatl number by a specified number of bits.
 * 
 * This function performs a left bitwise shift on a 128-bit integer 
 * (floatl). The shift amount can be greater than 32 bits, in which case 
 * the function calculates how many whole 32-bit parts to shift and 
 * how many bits to shift within the remaining part. It constructs 
 * the result based on the input number after applying the shift.
 * 
 * \param[in] a: The floatl number to shift.
 * \param[in] amount: The number of bits to shift to the left.
 * \return The left-shifted floatl number.
 */
static floatl2 floatl2_int_shl(floatl2 a, uint32_t amount) 
{
    floatl2 result = {0}; // Initialize the result to zero
    int u32bias = amount / 32; // Number of whole 32-bit parts to shift
    int bitsbias = amount % 32; // Remaining bits to shift

    // Perform the shift for each 32-bit part of the floatl number
    for (int i = 0; i < __FLOATL2_U32_PARTS__; i++) 
    {
        if (i < u32bias)
        {
            result.u32[i] = 0; // Set shifted-out parts to zero
        }
        else 
        {
            // Shift the current part and add bits from the previous part if needed
            result.u32[i] = (a.u32[i - u32bias] << bitsbias) | 
                (((i - u32bias - 1) >= 0 && bitsbias > 0) ? 
                (a.u32[i - u32bias - 1] >> (32 - bitsbias)) : 0);
        }
    }
    return result; // Return the left-shifted result
}

/** 
 * \brief Determines the sign of an floatl number.
 * 
 * This function checks the sign of the given 128-bit unsigned integer 
 * (floatl) based on its representation. It first examines the most significant 
 * bit of the highest 32-bit segment to determine if the number is negative. 
 * If this bit is set, the function returns -1, indicating a negative value. 
 * If all segments are zero, it returns 0, indicating that the number is zero. 
 * If the number is positive, it returns 1.
 * 
 * \param[in] a: The floatl number to evaluate for its sign.
 * \return -1 if the number is negative, 0 if the number is zero, and 
 *         1 if the number is positive.
 */
static int floatl2_int_sign(floatl2 a)
{
    // Check if the sign bit of the highest 32-bit part is set
    if (a.u32[__FLOATL2_U32_PARTS__ - 1] & 0x80000000) return -1;

    // Check if the number is zero
    for (int i = __FLOATL2_U32_PARTS__ - 1; i >= 0; i--) 
    {
        if (a.u32[i] != 0) return 1; // Return 1 if any part is non-zero
    }
    
    return 0; // Return 0 if all parts are zero
}

/** 
 * \brief Adds two floatl numbers.
 * 
 * This function computes the sum of two 128-bit integers 
 * (floatl). It processes each 16-bit part of the input integers, 
 * handling carry bits as necessary. The result is stored in a 
 * new floatl number. This function ensures that overflow is 
 * correctly managed across all parts.
 * 
 * \param[in] a: The first operand (floatl number).
 * \param[in] b: The second operand (floatl number).
 * \return The sum of a and b as an floatl (128-bit integer).
 */
static floatl2 floatl2_int_add(floatl2 a, floatl2 b) 
{
    floatl2 result; // Initialize the result variable
    uint16_t carry = 0; /** Carry bit */

    // Perform addition for each 16-bit part
    for (int i = 0; i < __FLOATL2_U16_PARTS__; i++) 
    {
        // Calculate the sum of corresponding parts and carry
        uint32_t sum = (uint32_t)a.u16[i] + (uint32_t)b.u16[i] + carry;
        result.u16[i] = (uint16_t)(sum & 0xFFFF); /** Lower 16 bits */
        carry = (sum >> 16) & 0xFFFF; /** Upper 16 bits as carry */
    }

    return result; // Return the resulting floatl number
}

/** 
 * \brief Subtracts one floatl number from another.
 * 
 * This function computes the difference of two 128-bit integers 
 * (floatl). It processes each 16-bit part of the minuend and 
 * subtrahend, handling borrow bits as necessary. The result is 
 * stored in a new floatl number. This function ensures that 
 * borrowing is correctly managed across all parts.
 * 
 * \param[in] a: The minuend (the number from which another is to be subtracted).
 * \param[in] b: The subtrahend (the number to be subtracted).
 * \return The result of a - b as an floatl (128-bit integer).
 */
static floatl2 floatl2_int_sub(floatl2 a, floatl2 b) 
{
    floatl2 result; // Initialize the result variable

    // Perform subtraction for each 16-bit part
    for (int i = 0; i < __FLOATL2_U16_PARTS__; i++) 
    {
        uint32_t diff = (uint32_t)a.u16[i] - (uint32_t)b.u16[i];
        
        // Check if a borrow occurred
        if (diff & 0xFFFF0000) /** Borrow occurred */
        {
            // Adjust the higher parts to account for the borrow
            for (int j = i + 1; j < __FLOATL2_U16_PARTS__; j++) 
            {
                a.u16[j] -= 1; // Borrow from the next part
                if (a.u16[j] != 0xFFFF) break; // Stop if no further borrow needed
            }
        }
        
        // Store the result of the subtraction
        result.u16[i] = (uint16_t)(diff & 0xFFFF);
    }

    return result; // Return the resulting floatl number
}

/** 
 * \brief Multiplies two floatl unsigned numbers.
 * 
 * This function performs multiplication of two 128-bit unsigned integers 
 * (floatl) by using a method similar to the schoolbook algorithm. The 
 * multiplication is carried out by breaking the numbers into their 
 * 16-bit components and accumulating the results. The function handles 
 * carry-over during the multiplication and addition stages to ensure 
 * the final product is accurately represented.
 * 
 * \param[in] a: The first operand to multiply.
 * \param[in] b: The second operand to multiply.
 * \return The product of a and b as an floatl (128-bit unsigned integer).
 */
static floatl2 floatl2_int_umul(floatl2 a, floatl2 b) 
{
    floatl2 result = {0}; /** Initialize the result to 0 */
    floatl2 temp[__FLOATL_U16_PARTS__*2] = {{0}}; // Temporary storage for intermediate results
    uint16_t carry = 0; // Variable to hold carry-over during multiplication

    // Perform multiplication
    for (int i = 0; i < __FLOATL2_U16_PARTS__; i++) 
    {
        carry = 0; // Reset carry for the current row
        for (int j = 0; j < __FLOATL2_U16_PARTS__; j++) 
        {
            if (i + j < __FLOATL2_U16_PARTS__) 
            {
                // Multiply the 16-bit segments and add carry
                uint32_t mul = (uint32_t)a.u16[i] * (uint32_t)b.u16[j] + carry;
                temp[i].u16[i + j] = (mul & 0xFFFF); // Store the lower 16 bits
                carry = ((mul >> 16) & 0xFFFF); // Update carry for the next addition
            }
        }
    }

    carry = 0; // Reset carry for the addition phase
    // Combine results from the temporary storage
    for (int i = 0; i < __FLOATL2_U16_PARTS__; i++) 
    {
        uint32_t add = 0; // Variable to hold the sum of the current column
        for (int j = 0; j < __FLOATL2_U16_PARTS__; j++) 
        {
            add += temp[j].u16[i]; // Accumulate results from temp
        }
        add += carry; // Add any carry from the previous column
        result.u16[i] = (add & 0xFFFF); // Store the lower 16 bits in result
        carry = ((add >> 16) & 0xFFFF); // Update carry for the next column
    }

    return result; // Return the final product
}

/** 
 * \brief Divides one floatl unsigned number by another.
 * 
 * This function performs division of one 128-bit unsigned integer (floatl) 
 * by another. It calculates the quotient using a bitwise approach, 
 * handling division by zero gracefully. The result is built bit by bit 
 * from the most significant bit to the least significant bit. If the 
 * divisor is zero, it prints an error message and returns zero.
 * 
 * \param[in] a: The dividend (number to be divided).
 * \param[in] b: The divisor (number to divide by).
 * \return The quotient of a divided by b as an floatl (128-bit unsigned integer).
 */
static floatl2 floatl2_int_udiv(floatl2 a, floatl2 b, floatl2 *mod)  
{
    int FLOATL2_BIT_PARTS = __FLOATL_BIT_PARTS__ * 2;
    // Check for division by zero
    if (floatl2_int_sign(b) == 0)
    {
        printf("Division by zero!\n");
        return FLOATL2(__FLOATL_INT_ZERO__); /** Handle division by zero */
    }

    floatl2 result = {0};      // Initialize the result to zero
    floatl2 remainder = {0};   // Initialize the remainder to zero

    /** Calculate bit by bit from the highest bit */
    for (int i = FLOATL2_BIT_PARTS - 1; i >= 0; i--) 
    {
        /** Left shift remainder and add current bit */
        remainder = floatl2_int_shl(remainder, 1); // Shift remainder left by 1
        remainder.u32[0] |= (a.u32[i / 32] >> (i % 32)) & 1; // Add current bit from dividend

        /** If remainder is greater than or equal to b, subtract b */
        if (floatl2_int_ucmp(remainder, b) >= 0) 
        {
            remainder = floatl2_int_sub(remainder, b); // Subtract b from remainder
            result.u32[i / 32] |= (1 << (i % 32)); // Set corresponding bit in result
        }
    }

    if (mod) *mod = remainder;

    return result; // Return the final quotient
}

/**
 * \brief Calculate 10 raised to the power of the given integer exponent.
 * \param[in] n: The exponent to which 10 is raised. It can be a positive or negative 32 - bit integer.
 * \return A 'floatl' value representing 10^n.
 * 
 * This function calculates 10^n by dividing the exponent into segments of 15.
 * For positive exponents, it multiplies the result by pre - computed powers of 10.
 * For negative exponents, it divides the result by pre - computed powers of 10.
 */
static floatl floatl_pow10(int32_t n)
{
    // Initialize the result to 1 (10^0)
    floatl number = FLOATL_CONST_1;

    if (n > 0)
    {
        // Calculate 10^n for positive exponents, dividing the exponent into segments of 15
        while (n != 0)
        {
            if (n > 15) {
                // If the exponent is greater than 15, multiply the result by 10^15 and reduce the exponent by 15
                number = floatl_mul(number, flpow10[15]);
                n -= 15;
            }
            else {
                // If the remaining exponent is less than or equal to 15, multiply the result by 10^n
                number = floatl_mul(number, flpow10[n]);
                n = 0;
            }
        }
    }
    else if (n < 0)
    {
        // Calculate 10^n for negative exponents, dividing the exponent into segments of 15
        while (n != 0)
        {
            if (n < -15) {
                // If the absolute value of the exponent is greater than 15, divide the result by 10^15 and increase the exponent by 15
                number = floatl_div(number, flpow10[15]);
                n += 15;
            }
            else {
                // If the absolute value of the remaining exponent is less than or equal to 15, divide the result by 10^(-n)
                number = floatl_div(number, flpow10[-n]);
                n = 0;
            }
        }
    }

    return number;
}

/**
 * \brief Convert a hexadecimal character to its corresponding numerical value.
 * \param[in] c: The hexadecimal character to be converted. It can be a digit from '0' to '9',
 *               a lowercase letter from 'a' to 'f', or an uppercase letter from 'A' to 'F'.
 * \return The numerical value corresponding to the hexadecimal character. Returns -1 if the input
 *         character is not a valid hexadecimal character.
 * 
 * This function takes a single hexadecimal character and converts it to its numerical equivalent.
 * For digits '0' - '9', it returns the digit value. For letters 'a' - 'f' or 'A' - 'F', it returns
 * the corresponding value from 10 to 15.
 */
static char hexI(char c)
{
    // Check if the character is a digit from '0' to '9'
    if (c >= '0' && c <= '9') {
        // If it is a digit, return its numerical value
        return c - '0';
    }
    // Check if the character is a lowercase letter from 'a' to 'f'
    else if (c >= 'a' && c <= 'f') {
        // If it is a lowercase letter, return the corresponding value (10 - 15)
        return c - 'a' + 10;
    }
    // Check if the character is an uppercase letter from 'A' to 'F'
    else if (c >= 'A' && c <= 'F') {
        // If it is an uppercase letter, return the corresponding value (10 - 15)
        return c - 'A' + 10;
    }
    // If the character is not a valid hexadecimal character, return -1
    return -1;
}

/**
 * \brief Fill the mantissa area of a 'floatl' number with a character value.
 * \param[in,out] number: Pointer to the 'floatl' structure where the mantissa will be updated.
 * \param[in,out] part: Pointer to an integer representing the current u32 part index in the mantissa area.
 * \param[in,out] bitoffset: Pointer to an integer representing the current bit offset within the u32 part.
 * \param[in,out] bitnum: Pointer to an integer representing the number of bits to fill.
 * \param[in] c: The character value to be filled into the mantissa area.
 * \return 1 if the filling operation is successful, 0 if an error occurs (e.g., part index goes out of bounds).
 * 
 * This function takes a character value and fills it into the mantissa area of a 'floatl' number.
 * It handles the bit offset and part index to ensure the value is placed correctly in the mantissa.
 */
static int pad_mant(floatl *number, int *part, int *bitoffset, int *bitnum, char c)
{
    // Update the remaining number of bits at the current bit offset
    (*bitoffset) -= (*bitnum);

    // If the bit offset is negative, we need to move to the previous u32 part
    if ((*bitoffset) < 0)
    {
        (*part)--;

        // If the u32 part index becomes negative, we need to adjust further
        if ((*part) < 0)
        {
            // Check if the total number of bits to fill is exactly 32. If so, return an error.
            if ((*bitoffset) + (*bitnum) == 32) return 0;
            else 
            {
                // Reset the part index to 0
                (*part) = 0;
                // Adjust the number of bits to fill based on the remaining space in the previous part
                (*bitnum) -= (32 - (*bitoffset));
                // Reset the bit offset to 0
                (*bitoffset) = 0;
            }
        }

        // Update the bit offset within the current part
        (*bitoffset) += 32;
    }

    // If the current part belongs to the mantissas array
    if ((*part) < __FLOATL_MANT_PARTS__)
    {
        // Concatenate the character 'c' to the mantissas array
        number->mantissas[(*part)] |= (c << (*bitoffset));

        // If there isn't enough space in the current u32 part to fit the entire character,
        // we need to continue filling the remaining part into the next higher u32 part
        if ((*bitoffset) + (*bitnum) >= 32)
        {
            // If there is a next part in the mantissas array, fill the remaining part there
            if ((*part) + 1 < __FLOATL_MANT_PARTS__) number->mantissas[(*part) + 1] |= (c >> (32 - (*bitoffset)));
            // Otherwise, fill the remaining part into the high - order mantissa
            else number->mantissa |= (c >> (32 - (*bitoffset)));
        }
    }
    // If the current part belongs to the high - order mantissa
    else 
    {
        // Concatenate the character 'c' to the high - order mantissa
        number->mantissa |= (c << (*bitoffset));
    }

    return 1;
}

/**
 * \brief Convert a string representation of a floating - point number to a 'floatl' type.
 * \param[in] str: Pointer to the null - terminated string representing the floating - point number.
 * \return A 'floatl' value representing the converted floating - point number. Returns FLOATL_NAN if the input string is invalid.
 * 
 * This function parses a string to create a 'floatl' number. It supports both hexadecimal (starting with "0x")
 * and decimal formats. It handles signs, integer parts, decimal parts, and exponents appropriately.
 */
floatl floatl_from(const char *str)
{
    // Initialize the result number to 0
    floatl number = FLOATL_CONST_0;
    const char *text = str;
    int sign = 1, scale = 0;            /* Sign and scale of integer part */
    int e_sign = 1, e_scale = 0;        /* Sign and scale of exponent part */
    int p_sign = 1, p_scale = 0;        /* Sign and scale of pico part */

    // Skip leading whitespace characters
    while (*text <= ' ') text++;

    // Check if the number is negative
    if (*text == '-')
    {
        sign = -1;
        text++;
    }

    // Check if the number starts with '0'
    if (*text == '0')
    {
        // Skip leading '0's
        while (*text == '0') text++;

        // Check if it is a hexadecimal number (starts with "0x" or "0X")
        if (*text == 'x' || *text == 'X')
        {
            text++;

            // Skip leading '0's after "0x"
            while (*text == '0') text++;

            char c = 0;
            char hide = 0;
            int exp = 0;
            int part = __FLOATL_MANT_PARTS__;
            int bitoffset = __FLOATL_MANT_HIGH_BITS__;
            int bitnum = 0;

            // Parse the integer part of the hexadecimal number
            while (1)
            {
                c = hexI(*text);
                if (c < 0) break;
                text++;

                // For the first digit, remove the hidden bit
                if (!hide)
                {
                    bitnum = 32 - count_u32_leading_zero(c) - 1;
                    c &= ((1 << bitnum) - 1);
                    hide = 1;
                }
                else bitnum = 4;

                if (!pad_mant(&number, &part, &bitoffset, &bitnum, c)) break;

                exp += bitnum;
            }

            // Parse the decimal part of the hexadecimal number
            if (*text == '.')
            {
                text++;

                while (1)
                {
                    c = hexI(*text);
                    if (c < 0) break;
                    text++;

                    // For the first digit, remove the hidden bit
                    if (!hide)
                    {
                        if (c == 0)
                        {
                            exp -= 4;
                            continue;
                        }
                        else 
                        {
                            bitnum = 32 - count_u32_leading_zero(c) - 1;
                            exp -= (4 - bitnum);
                            c &= ((1 << bitnum) - 1);
                            hide = 1;
                        }
                    }
                    else bitnum = 4;

                    if (!pad_mant(&number, &part, &bitoffset, &bitnum, c)) break;
                }
            }

            // Parse the pico part (exponent part in hexadecimal format)
            if (*text == 'p' || *text == 'P')
            {
                text++;

                // Skip '+' sign
                if (*text == '+') text++;
                // Handle '-' sign
                else if (*text == '-')
                {
                    p_sign = -1;
                    text++;
                }

                // Check if the first character of the exponent is a valid digit
                if (!(*text >= '0' && *text <= '9')) 
                { 
                    return FLOATL_NAN;  
                }

                // Convert the exponent part
                while (*text >= '0' && *text <= '9') 
                { 
                    p_scale = (p_scale * 10) + (*text++ - '0'); /* number */
                }
            }

            // Apply the sign to the pico part
            if (p_sign < 0) p_scale = -p_scale;

            // Update the exponent
            exp += p_scale;

            // Check for overflow
            if (exp > __FLOATL_EXP_MID_VALUE__)
            {
                floatl inf = FLOATL_INF;
                inf.sign = sign > 0 ? 0 : 1;
                return inf;
            }
            // Check for underflow
            else if (exp < -__FLOATL_EXP_MID_VALUE__ - 1)
            {
                floatl zoro = FLOATL_CONST_0;
                zoro.sign = sign > 0 ? 0 : 1;
                return zoro;
            }

            // Set the sign and exponent of the result number
            number.sign = sign > 0 ? 0 : 1;
            number.exponent = __FLOATL_EXP_MID_VALUE__ + exp;

            return number;
        }
    }

    // Parse the integer part of the decimal number
    if (*text >= '1' && *text <= '9')
    {
        do
        {
            // Multiply the number by 10 and add the current digit
            number = floatl_mul(number, FLOATL_CONST_10); /* carry addition */
            number = floatl_add(number, floatl_from_d((double)(*text++ - '0')));
        } while (*text >= '0' && *text <= '9');
    }

    // Parse the decimal part of the decimal number
    if (*text == '.')
    {
        text++;

        // Check if the first character of the decimal part is a valid digit
        if (!(*text >= '0' && *text <= '9')) 
        { 
            return FLOATL_NAN; 
        }

        // Multiply the number by 10 and add the current digit, and adjust the scale
        do
        {
            number = floatl_mul(number, FLOATL_CONST_10);
            number = floatl_add(number, floatl_from_d((double)(*text++ - '0')));
            scale--;
        } while (*text >= '0' && *text <= '9');
    }

    // Parse the exponent part of the decimal number
    if (*text == 'e' || *text == 'E')
    {
        text++;

        // Skip '+' sign
        if (*text == '+') text++;
        // Handle '-' sign
        else if (*text == '-')
        {
            e_sign = -1;
            text++;
        }

        // Check if the first character of the exponent is a valid digit
        if (!(*text >= '0' && *text <= '9')) 
        { 
            return FLOATL_NAN;  
        }

        // Convert the exponent part
        while (*text >= '0' && *text <= '9') 
        { 
            e_scale = (e_scale * 10) + (*text++ - '0'); /* number */
        }
    }

    // Calculate the final result
    number = floatl_mul(number, floatl_pow10(scale + e_scale * e_sign));
    number.sign = sign > 0 ? 0 : 1;

    return number;
}

/**
 * \brief Convert a double - precision floating - point number (double) to a 'floatl' type.
 * \param[in] value: The double - precision floating - point number to be converted.
 * \return A 'floatl' value representing the converted number. Returns FLOATL_NAN if the input is NaN,
 *         FLOATL_INF if the input is infinity, and the converted value otherwise.
 * 
 * This function takes a double value and converts it to a 'floatl' value. It first checks if the input
 * is NaN or infinity and sets the result accordingly. Otherwise, it extracts the mantissa and exponent
 * from the double and adjusts them to fit the 'floatl' format.
 */
floatl floatl_from_d(double value)
{
    // Initialize the result to 0
    floatl result = {0};
    // Union to access the double value as its components
    double_u f = {.float_ = value};

    // Check if the input is NaN
    if (f.exponent == 2047 && (f.mantissa_h != 0 || f.mantissa_l != 0))
    {
        result = FLOATL_NAN;
    }
    // Check if the input is infinity
    else if (f.exponent == 2047 && (f.mantissa_h == 0 && f.mantissa_l == 0))
    {
        result = FLOATL_INF;
    }
    else 
    {
        // Extract the low and high parts of the mantissa from the double and store them in the 'floatl' mantissa
        result.mantissas[0] = f.mantissa_l;
        result.mantissas[1] = f.mantissa_h;
        // Shift the mantissa to the appropriate position in the 'floatl' format
        result = floatl_int_shl(result, __FLOATL_MANT_BITS__ - 52);
        // Adjust the exponent to fit the 'floatl' format
        result.exponent = (uint32_t)(((int32_t)f.exponent - 1023) + __FLOATL_EXP_MID_VALUE__);
    }

    // Set the sign of the 'floatl' result
    result.sign = f.sign;

    return result;
}


/**
 * \brief Converts a custom floating-point type (floatl) to a double precision floating-point number.
 * \param a: The input value of the custom floating-point type (floatl) that needs to be converted.
 * \return A double precision floating-point number which is the converted result of the input floatl value.
 * 
 * This function is mainly responsible for converting a value of the custom floating-point type 'floatl'
 * to a standard double precision floating-point number. It first checks if the 'floatl' type uses 64 bits
 * for storage by checking the preprocessor macro 'FLOATL_USE_64BITS'. If it does, it simply copies the memory
 * of the 'floatl' variable to a 'double_u' structure and returns the corresponding floating-point value.
 * Otherwise, it proceeds with a series of operations for the conversion.
 */
double floatl_to_d(floatl a)
{
    double_u du;

    // If the 'floatl' type uses 64 bits (same as the size of 'double'), directly copy the memory
    // and return the stored value as a 'double'.
    #if defined(FLOATL_USE_64BITS)
    memcpy(&du, &a, sizeof(double));
    return du.float_;
    #endif

    // Extract the exponent part from the input 'floatl' value. Subtract the middle value of the exponent
    // range defined for 'floatl' (__FLOATL_EXP_MID_VALUE__) to get a relative exponent value.
    int32_t exp = a.exponent - __FLOATL_EXP_MID_VALUE__;
    // Create a new 'floatl' variable'mant' initialized with the input 'a', and then set its sign and exponent
    // to 0 to isolate just the mantissa part of the original 'floatl' value.
    floatl mant = a; mant.sign = 0; mant.exponent = 0U;
    // Set the sign of the result to be the same as the sign of the input 'floatl' value.
    bool sign = a.sign;

    // Handle special cases such as NaN (Not a Number) and infinity. If the exponent of the input 'floatl'
    // is equal to the whole value of the exponent range defined for 'floatl' (__FLOATL_EXP_WHL_VALUE__),
    // it indicates a special value.
    if (a.exponent == __FLOATL_EXP_WHL_VALUE__) 
    {
        // If the mantissa has a sign (checked by 'floatl_int_sign' function), set the high and low parts
        // of the 'int_' structure within 'double_u' to all 1s (representing a special NaN or infinity case).
        if (floatl_int_sign(mant))
        {
            du.int_.high = 0xFFFFFFFF;
            du.int_.low = 0xFFFFFFFF;
        }
        else 
        {
            // Otherwise, set the high and low parts to 0.
            du.int_.high = 0;
            du.int_.low = 0;
        }

        // Set the sign and exponent of the 'double_u' structure according to the rules for special values.
        du.sign = sign;
        du.exponent = 2047;

        // Return the resulting 'double' value representing the special value.
        return du.float_;
    }

    // Adjust the extracted exponent to fit within the exponent range of a standard double precision
    // floating-point number (-1022 to 1023). Add 1023 to convert it to the biased exponent form
    // used by doubles.
    exp += 1023;

    // Check for overflow. If the adjusted exponent is greater than 2047 (the maximum exponent value
    // for a double), it means an overflow has occurred, and we return positive or negative infinity
    // depending on the sign.
    if (exp > 2047) 
    {
        du.int_.high = 0;
        du.int_.low = 0;
        du.sign = sign;
        du.exponent = 2047;

        return du.float_;
    } 
    // Check for underflow. If the adjusted exponent is less than 0, it means an underflow has occurred,
    // and we return 0.
    else if (exp < 0) 
    {
        du.int_.high = 0;
        du.int_.low = 0;
        du.sign = sign;
        du.exponent = 0;

        return du.float_;
    }

    // Add the hidden bit (which is 1 in the normalized representation of floating-point numbers)
    // to the mantissa. Use the 'floatl_int_or' function to perform a bitwise OR operation to set the
    // hidden bit.
    mant = floatl_int_or(mant, __FLOATL_HIDE_MANT_BIT__);

    // Calculate the number of bits that need to be discarded from the mantissa to fit it into the
    // 52-bit mantissa of a double precision floating-point number. Subtract 52 from the total number
    // of mantissa bits defined for 'floatl' (__FLOATL_MANT_BITS__).
    int32_t discard_bits = __FLOATL_MANT_BITS__ - 52;

    // Keep only the highest 52 bits of the mantissa. Use the 'floatl_int_shr' function to shift
    // the mantissa right by the number of bits to be discarded.
    floatl double_mant = floatl_int_shr(mant, discard_bits);

    // Create a 'floatl' variable 'int1' representing the integer value 1. Initialize its first 32-bit
    // part (u32[0]) to 1.
    floatl int1 = __FLOATL_CONST_0__; int1.u32[0] = 1;

    // Get the highest bit among the bits to be discarded. Use the 'floatl_int_shl' function to shift
    // 'int1' left by the number of bits equal to the number of bits to be discarded minus 1.
    // This bit will be used for rounding purposes.
    floatl high_bit = floatl_int_shl(int1, discard_bits - 1);

    // Get the bits that will be discarded from the mantissa. Use the 'floatl_int_and' function to perform
    // a bitwise AND operation between the original mantissa and a value that represents the bits to be
    // discarded (formed by first shifting 'int1' left by the number of bits to be discarded and then
    // decrementing it using 'floatl_int_dec').
    floatl round_bits = floatl_int_and(mant, floatl_int_dec(floatl_int_shl(int1, discard_bits)));

    // Determine whether rounding is needed. If the bits to be discarded ('round_bits') are greater than
    // the highest bit among them ('high_bit'), or if they are equal and the lowest bit of the remaining
    // mantissa ('double_mant') is 1 (checked by 'floatl_int_sign' function), then rounding is required.
    if (floatl_int_cmp(round_bits, high_bit) > 0 || 
        (floatl_int_cmp(round_bits, high_bit) == 0 && floatl_int_sign(floatl_int_and(double_mant, int1)))) 
    {
        // Perform rounding by incrementing the remaining mantissa. Use the 'floatl_int_inc' function.
        floatl_int_inc(double_mant);

        // Check if the increment of the mantissa causes a carry to the exponent part. If the sign bit
        // of the result of a bitwise AND operation between the remaining mantissa and a value representing
        // the bit position 2 bits higher than the hidden bit position (shifted 'int1' left by 52 + 2)
        // is 1, it means there is a carry to the exponent.
        if (floatl_int_sign(floatl_int_and(double_mant, floatl_int_shl(int1, 52 + 2)))) 
        {
            // If there is a carry to the exponent, shift the remaining mantissa right by 1 bit
            // to make room for the carry in the exponent. Use the 'floatl_int_shr' function.
            double_mant = floatl_int_shr(double_mant, 1);
            // Increment the exponent by 1.
            exp += 1;

            // Check for a secondary overflow of the exponent. If the exponent after the increment is
            // greater than 2047, it means another overflow has occurred, and we return positive or
            // negative infinity depending on the sign.
            if (exp > 2047) 
            {
                du.int_.high = 0;
                du.int_.low = 0;
                du.sign = sign;
                du.exponent = 2047;
                return du.float_;
            }
        }
    }

    // Combine the processed mantissa, sign, and exponent to form the final 'double' value.
    // Set the high and low parts of the 'int_' structure within 'double_u' to the corresponding parts
    // of the remaining mantissa.
    du.int_.high = double_mant.u32[1];
    du.int_.low = double_mant.u32[0];
    // Set the sign of the 'double_u' structure.
    du.sign = sign;
    // Set the exponent of the 'double_u' structure.
    du.exponent = exp;

    // Return the final converted double precision floating-point number.
    return du.float_;
}

/**
 * \brief Get the sign of a 'floatl' number.
 * \param[in] a: The 'floatl' number whose sign is to be determined.
 * \return The sign of the 'floatl' number. It returns the value of the 'sign' field in the 'floatl' structure.
 * 
 * This function simply extracts and returns the sign bit of the given 'floatl' number.
 */
int floatl_sign(floatl a)
{
    return a.sign;
}

/**
 * \brief Check if a 'floatl' number is NaN (Not a Number).
 * \param[in] a: The 'floatl' number to be checked.
 * \return 1 if the 'floatl' number is NaN, 0 otherwise.
 * 
 * This function checks if the 'floatl' number is NaN by performing a bitwise AND operation
 * between the number and a mask (__FLOATL_ALL_EXP_MANT__) and then comparing the result
 * with the representation of infinity (__FLOATL_INF__). If the result is greater than the
 * infinity representation, the number is considered NaN.
 */
int floatl_isnan(floatl a)
{
    return floatl_int_ucmp(floatl_int_and(a, __FLOATL_ALL_EXP_MANT__), __FLOATL_INF__) > 0;
}

/**
 * \brief Check if a 'floatl' number is infinity.
 * \param[in] a: The 'floatl' number to be checked.
 * \return 1 if the 'floatl' number is infinity, 0 otherwise.
 * 
 * This function checks if the 'floatl' number is infinity by performing a bitwise AND operation
 * between the number and a mask (__FLOATL_ALL_EXP_MANT__) and then comparing the result
 * with the representation of infinity (__FLOATL_INF__). If the result is equal to the
 * infinity representation, the number is considered infinity.
 */
int floatl_isinf(floatl a)
{
    return floatl_int_ucmp(floatl_int_and(a, __FLOATL_ALL_EXP_MANT__), __FLOATL_INF__) == 0;
}

/**
 * \brief Check if a 'floatl' number is a normal number.
 * \param[in] a: The 'floatl' number to be checked.
 * \return 1 if the 'floatl' number is a normal number, 0 otherwise.
 * 
 * A normal number is defined as a number whose exponent is neither 0 nor the maximum possible
 * exponent value (__FLOATL_EXP_WHL_VALUE__). This function checks these conditions and
 * returns the appropriate result.
 */
int floatl_isnormal(floatl a)
{
    return ((a.exponent != 0) && (a.exponent != __FLOATL_EXP_WHL_VALUE__));
}

/**
 * \brief Compare if a 'floatl' number 'a' is less than another 'floatl' number 'b'.
 * \param[in] a: The first 'floatl' number to be compared.
 * \param[in] b: The second 'floatl' number to be compared.
 * \return true if 'a' is less than 'b', false otherwise.
 * 
 * This function compares two 'floatl' numbers to determine if 'a' is less than 'b'.
 * It first checks the signs of the two numbers. If the signs are different,
 * it checks if 'a' is negative and the result of a bit - shifted OR operation of 'a' and 'b' is non - zero.
 * If the signs are the same, it checks if the two numbers are not equal and applies a condition based on the sign.
 */
static bool floatl_real_lt(floatl a, floatl b)
{
    // Extract the sign of 'a'
    bool sign1 = a.sign;
    // Extract the sign of 'b'
    bool sign2 = b.sign;
    // Check if the signs of the two numbers are different
    if (sign1 != sign2) // This can also be checked using XOR
    {
        // If 'a' is negative and the result of a bit - shifted OR operation of 'a' and 'b' is non - zero,
        // then 'a' is less than 'b'
        return sign1 && floatl_int_sign(floatl_int_shl(floatl_int_or(a, b), 1));
    }
    // If the signs are the same, 'a' is less than 'b' if the two numbers are not equal
    // and for positive numbers, the one with a smaller absolute value is smaller,
    // while for negative numbers, the one with a larger absolute value is smaller
    return (floatl_int_ucmp(a, b)) && (sign1 ^ (floatl_int_ucmp(a, b) < 0));
}

/**
 * \brief Compare if a 'floatl' number 'a' is less than or equal to another 'floatl' number 'b'.
 * \param[in] a: The first 'floatl' number to be compared.
 * \param[in] b: The second 'floatl' number to be compared.
 * \return true if 'a' is less than or equal to 'b', false otherwise.
 * 
 * This function compares two 'floatl' numbers to determine if 'a' is less than or equal to 'b'.
 * It first checks the signs of the two numbers. If the signs are different,
 * it checks if 'a' is negative or the result of a bit - shifted OR operation of 'a' and 'b' is zero.
 * If the signs are the same, it checks if the two numbers are equal or the appropriate condition based on the sign holds.
 */
static bool floatl_real_le(floatl a, floatl b)
{
    // Extract the sign of 'a'
    bool sign1 = a.sign;
    // Extract the sign of 'b'
    bool sign2 = b.sign;
    // Check if the signs of the two numbers are different
    if (sign1 != sign2)
    {
        // Different from the 'lt' function, the numbers can be zero here.
        // If 'a' is negative or the result of a bit - shifted OR operation of 'a' and 'b' is zero,
        // then 'a' is less than or equal to 'b'
        return sign1 || (floatl_int_sign(floatl_int_shl(floatl_int_or(a, b), 1)) == 0);
    }
    // Different from the 'lt' function, we check for equality or less - than condition.
    // 'a' is less than or equal to 'b' if the two numbers are equal or the appropriate condition based on the sign holds.
    return (!floatl_int_ucmp(a, b)) || (sign1 ^ (floatl_int_ucmp(a, b) < 0));
}

/**
 * \brief Check if two 'floatl' numbers are equal.
 * \param[in] a: The first 'floatl' number to be compared.
 * \param[in] b: The second 'floatl' number to be compared.
 * \return 1 if the two numbers are equal, 0 otherwise.
 * 
 * This function first checks if either of the numbers is a NaN (Not a Number).
 * If so, it immediately returns 0 because NaN is not equal to any number, including itself.
 * Otherwise, it checks if the two numbers are equal by comparing their bit - representations
 * using floatl_int_ucmp. It also considers the case where both numbers might be zero
 * by using floatl_int_sign and floatl_int_shl along with floatl_int_or.
 */
int floatl_eq(floatl a, floatl b)
{
    // If either number is a NaN, they are not equal
    if (floatl_isnan(a) || floatl_isnan(b))
        return 0;
    return
        // Check if the bit - representations of the two numbers are equal
        (!floatl_int_ucmp(a, b)) || 
        // Check if both numbers are effectively zero
        ((floatl_int_sign(floatl_int_shl(floatl_int_or(a, b), 1)) == 0));
}

/**
 * \brief Check if two 'floatl' numbers are not equal.
 * \param[in] a: The first 'floatl' number to be compared.
 * \param[in] b: The second 'floatl' number to be compared.
 * \return 1 if the two numbers are not equal, 0 otherwise.
 * 
 * This function simply negates the result of the floatl_eq function.
 * If floatl_eq returns 1 (equal), this function returns 0 (not equal), and vice versa.
 */
int floatl_ne(floatl a, floatl b)
{
    return !floatl_eq(a, b);
}

/**
 * \brief Check if the first 'floatl' number is less than the second.
 * \param[in] a: The first 'floatl' number to be compared.
 * \param[in] b: The second 'floatl' number to be compared.
 * \return 1 if a < b, 0 otherwise.
 * 
 * This function first checks if either of the numbers is a NaN.
 * If so, it returns 0 because NaN cannot be compared in a meaningful way.
 * Otherwise, it calls the floatl_real_lt function to perform the actual less - than comparison.
 */
int floatl_lt(floatl a, floatl b)
{
    if (floatl_isnan(a) || floatl_isnan(b))
        return 0;
    return floatl_real_lt(a, b);
}

/**
 * \brief Check if the first 'floatl' number is less than or equal to the second.
 * \param[in] a: The first 'floatl' number to be compared.
 * \param[in] b: The second 'floatl' number to be compared.
 * \return 1 if a <= b, 0 otherwise.
 * 
 * This function first checks if either of the numbers is a NaN.
 * If so, it returns 0. Otherwise, it calls the floatl_real_le function
 * to perform the actual less - than or equal comparison.
 */
int floatl_le(floatl a, floatl b)
{
    if (floatl_isnan(a) || floatl_isnan(b))
        return 0;
    return floatl_real_le(a, b);
}

/**
 * \brief Check if the first 'floatl' number is greater than the second.
 * \param[in] a: The first 'floatl' number to be compared.
 * \param[in] b: The second 'floatl' number to be compared.
 * \return 1 if a > b, 0 otherwise.
 * 
 * This function first checks if either of the numbers is a NaN.
 * If so, it returns 0. Otherwise, it negates the result of the floatl_real_le function
 * because a > b is equivalent to!(a <= b).
 */
int floatl_gt(floatl a, floatl b)
{
    if (floatl_isnan(a) || floatl_isnan(b))
        return 0;
    return !floatl_real_le(a, b);
}

/**
 * \brief Check if the first 'floatl' number is greater than or equal to the second.
 * \param[in] a: The first 'floatl' number to be compared.
 * \param[in] b: The second 'floatl' number to be compared.
 * \return 1 if a >= b, 0 otherwise.
 * 
 * This function first checks if either of the numbers is a NaN.
 * If so, it returns 0. Otherwise, it negates the result of the floatl_real_lt function
 * because a >= b is equivalent to!(a < b).
 */
int floatl_ge(floatl a, floatl b)
{
    if (floatl_isnan(a) || floatl_isnan(b))
        return 0;
    return !floatl_real_lt(a, b);
}

/**
 * \brief Compute the absolute value of a 'floatl' number.
 * \param[in] a: The 'floatl' number for which the absolute value is to be computed.
 * \return A 'floatl' number representing the absolute value of the input number.
 * 
 * This function takes a 'floatl' number and checks its sign bit. If the number is negative
 * (i.e., the sign bit is set), it clears the sign bit to make the number positive.
 * If the number is already positive, it remains unchanged.
 */
floatl floatl_abs(floatl a)
{
    // Check if the number is negative
    if (a.sign)
        // If negative, set the sign bit to 0 (make it positive)
        a.sign = 0;
    return a;
}

/**
 * \brief Compute the negation of a 'floatl' number.
 * \param[in] a: The 'floatl' number to be negated.
 * \return A 'floatl' number representing the negation of the input number.
 * 
 * This function takes a 'floatl' number and toggles its sign bit. If the number is positive,
 * it becomes negative; if the number is negative, it becomes positive.
 */
floatl floatl_neg(floatl a)
{
    // Toggle the sign bit of the number
    a.sign = !a.sign;
    return a;
}

/**
 * \brief Computes the ceiling of a 'floatl' number.
 * \param[in] a: The 'floatl' number for which the ceiling value is to be computed.
 * \return A 'floatl' number representing the ceiling of the input number.
 * 
 * This function calculates the ceiling of a 'floatl' number. The ceiling of a number is the smallest
 * integer that is greater than or equal to the given number.
 */
floatl floatl_ceil(floatl a)
{
    // Calculate the actual exponent value by subtracting the mid - point of the exponent range
    int32_t exponent = a.exponent - __FLOATL_EXP_MID_VALUE__;

    // If the exponent is negative, the number lies between - 1 and 1
    if (exponent < 0) 
    {
        // If the number is greater than 0, the ceiling is 1
        if (floatl_gt(a, FLOATL_CONST_0))
        {
            return FLOATL_CONST_1;
        } 
        // If the number is equal to 0, the ceiling is 0
        else if (floatl_eq(a, FLOATL_CONST_0)) 
        {
            return FLOATL_CONST_0;
        } 
        // If the number is less than 0, the ceiling is 0 (in the context of floating - point representation)
        else 
        {
            return floatl_neg(FLOATL_CONST_0);
        }
    }

    // Calculate the number of bits to shift to isolate the integer part
    int32_t shift = __FLOATL_MANT_BITS__ - exponent;

    // If the shift is less than or equal to 0, the number is already an integer
    if (shift <= 0) return a;

    // Create a floatl number with the least significant bit set to 1
    floatl int1 = FLOATL_CONST_0; 
    int1.u32[0] = 1;
    // Create a mask to isolate the fractional part
    floatl mask = floatl_int_sub(floatl_int_shl(int1, shift), int1);
    // Clear the fractional part of the number
    floatl result = floatl_int_and(a, floatl_int_not(mask));

    // If the result is less than the original number, increment the result
    if (floatl_lt(result, a)) 
    {
        result = floatl_add(result, FLOATL_CONST_1);
    }

    return result;
}

/**
 * \brief Computes the floor of a 'floatl' number.
 * \param[in] a: The 'floatl' number for which the floor value is to be computed.
 * \return A 'floatl' number representing the floor of the input number.
 * 
 * This function calculates the floor of a 'floatl' number. The floor of a number is the largest
 * integer that is less than or equal to the given number.
 */
floatl floatl_floor(floatl a)
{
    // Calculate the actual exponent value by subtracting the mid - point of the exponent range
    int32_t exponent = a.exponent - __FLOATL_EXP_MID_VALUE__;

    // If the exponent is negative, the number lies between - 1 and 1
    if (exponent < 0) 
    {
        // If the number is greater than or equal to 0, the floor is 0
        if (floatl_ge(a, FLOATL_CONST_0))
        {
            return FLOATL_CONST_0;
        } 
        // If the number is less than 0, the floor is - 1
        else 
        {
            return floatl_neg(FLOATL_CONST_1);
        }
    }

    // Calculate the number of bits to shift to isolate the integer part
    int32_t shift = __FLOATL_MANT_BITS__ - exponent;

    // If the shift is less than or equal to 0, the number is already an integer
    if (shift <= 0) return a;

    // Create a floatl number with the least significant bit set to 1
    floatl int1 = FLOATL_CONST_0; 
    int1.u32[0] = 1;
    // Create a mask to isolate the fractional part
    floatl mask = floatl_int_sub(floatl_int_shl(int1, shift), int1);
    // Clear the fractional part of the number
    floatl result = floatl_int_and(a, floatl_int_not(mask));

    // If the result is greater than the original number, decrement the result
    if (floatl_gt(result, a)) 
    {
        result = floatl_sub(result, FLOATL_CONST_1);
    }

    return result;
}

/**
 * \brief Rounds a 'floatl' number to the nearest integer.
 * \param[in] a: The 'floatl' number to be rounded.
 * \return A 'floatl' number representing the rounded value of the input number.
 * 
 * This function rounds a 'floatl' number to the nearest integer. If the fractional part
 * is 0.5 or greater, the number is rounded up; otherwise, it is rounded down.
 */
floatl floatl_round(floatl a)
{
    // Calculate the actual exponent value by subtracting the mid - point of the exponent range
    int32_t exponent = a.exponent - __FLOATL_EXP_MID_VALUE__;

    // If the exponent is negative, the number lies between - 1 and 1
    if (exponent < 0) 
    {
        if (floatl_gt(a, FLOATL_CONST_0))
        {
            // If the number is greater than 0, round up if it is greater than or equal to 0.5
            return (floatl_ge(a, floatl(0.5))) ? FLOATL_CONST_1 : FLOATL_CONST_0;
        } 
        else 
        {
            // If the number is less than 0, round down if it is less than or equal to - 0.5
            return (floatl_le(a, floatl(-0.5))) ? floatl_neg(FLOATL_CONST_1) : floatl_neg(FLOATL_CONST_0);
        }
    }

    // Calculate the number of bits to shift to isolate the integer part
    int32_t shift = __FLOATL_MANT_BITS__ - exponent;

    // If the shift is less than or equal to 0, the number is already an integer
    if (shift <= 0) return a;

    // Create a floatl number with the least significant bit set to 1
    floatl int1 = FLOATL_CONST_0; 
    int1.u32[0] = 1;
    // Create a mask to isolate the fractional part
    floatl mask = floatl_int_sub(floatl_int_shl(int1, shift), int1);
    // Clear the fractional part of the number to get the integer part
    floatl result = floatl_int_and(a, floatl_int_not(mask));
    // Extract the fractional part of the number
    floatl fractional = floatl_int_and(a, mask);

    // Check if the fractional part is greater than or equal to 0.5
    if (floatl_int_ucmp(fractional, floatl_int_shl(int1, shift - 1)) >= 0) 
    {
        // If so, round up the result
        result = floatl_add(result, FLOATL_CONST_1);
    }

    return result;
}

/**
 * \brief Perform a right shift operation on a 'floatl' value while preserving the sticky bit.
 * \param[in] mant: The 'floatl' value to be shifted.
 * \param[in] n: The number of bits to shift to the right.
 * \return A 'floatl' value representing the result of the right shift operation with the sticky bit preserved.
 * 
 * This function performs a right shift operation on the given 'floatl' value. If the number of bits to shift
 * is less than the total number of bits in a 'floatl' minus 1, it uses the floatl_int_shr function to perform
 * the shift. Then, it checks if there are any non - zero bits that would be shifted out by using floatl_int_sign
 * and floatl_int_shl. If so, it sets the least significant bit of the result to 1. If the number of bits to shift
 * is greater than or equal to the total number of bits in a 'floatl' minus 1, it checks if the original value
 * is non - zero and sets the least significant bit of the result accordingly.
 */
static floatl shift_right_sticky(floatl mant, uint32_t n)
{
    // Initialize the result to zero
    floatl res = __FLOATL_INT_ZERO__;
    if (n < __FLOATL_BIT_PARTS__ - 1) {
        // Perform the right shift operation
        res = floatl_int_shr(mant, n);
        // Check if there are non - zero bits shifted out
        if (floatl_int_sign(floatl_int_shl(mant, __FLOATL_BIT_PARTS__ - n)))
        {
            // Set the least significant bit of the result
            res.u32[0] |= 1;
        }
    }
    else {
        // Check if the original value is non - zero
        if (floatl_int_sign(mant))
        {
            // Set the least significant bit of the result
            res.u32[0] |= 1;
        }
    }
    return res;
}

/**
 * \brief Perform a right shift operation on the product of two 'floatl' values while preserving the sticky bit.
 * \param[in] mant1: The first 'floatl' value.
 * \param[in] mant2: The second 'floatl' value.
 * \return A 'floatl' value representing the result of the right shift operation on the product of the two 'floatl' values
 *         with the sticky bit preserved.
 * 
 * This function first multiplies the two given 'floatl' values using floatl2_int_umul and stores the result in a 'floatl2'
 * structure. Then, it performs a right shift operation on the product using floatl2_int_shr. It checks if there are any
 * non - zero bits that would be shifted out by using floatl2_int_sign and floatl2_int_shl. If so, it sets the least
 * significant bit of the result. Finally, it returns the lower part of the 'floatl2' result as a 'floatl' value.
 */
static floatl shift_right_sticky_fl2(floatl mant1, floatl mant2)
{
    // Initialize the result and temporary 'floatl2' structures to zero
    floatl2 res = {0};
    floatl2 temp = {0};

    // Multiply the two 'floatl' values
    temp = floatl2_int_umul(FLOATL2(mant1), FLOATL2(mant2));
    // Perform the right shift operation on the product
    res = floatl2_int_shr(temp, __FLOATL_MANT_BITS__ - 2);
    // Check if there are non - zero bits shifted out
    if (floatl2_int_sign(floatl2_int_shl(temp, __FLOATL_BIT_PARTS__ * 2 - (__FLOATL_MANT_BITS__ - 2))))
    {
        // Set the least significant bit of the result
        res.u32[0] |= 1;
    }

    // Return the lower part of the 'floatl2' result
    return res.low;
}

/**
 * \brief Perform a round - to - even operation on a 'floatl' value using the GRS (Guard, Round, Sticky) bits.
 * \param[in] mant: The 'floatl' value to be rounded.
 * \return A 'floatl' value representing the result of the round - to - even operation.
 * 
 * This function extracts the lower 3 bits (GRS bits) of the given 'floatl' value. Then, it shifts the 'floatl' value
 * to the right by 3 bits. It creates a 'floatl' value with the least significant bit set to 1. Based on the value of
 * the GRS bits and the least significant bit of the shifted value, it decides whether to increment the shifted value.
 * If the GRS bits are greater than 4 or equal to 4 and the least significant bit of the shifted value is 1, it increments
 * the shifted value using floatl_int_inc. Finally, it returns the rounded 'floatl' value.
 */
static floatl round_even_grs(floatl mant)
{
    // Extract the GRS (Guard, Round, Sticky) bits
    uint8_t grs = mant.u32[0] & 7;

    // Shift the 'floatl' value to the right by 3 bits
    mant = floatl_int_shr(mant, 3);

    // Create a 'floatl' value with the least significant bit set to 1
    floatl u1 = __FLOATL_INT_ZERO__;
    u1.u32[0] = 1U;
    // Check the conditions for rounding
    if ((grs > 4) || ((grs == 4) && (mant.u32[0] & 1)))
        // Increment the shifted value if the conditions are met
        mant = floatl_int_inc(mant);

    return mant;
}

/**
 * \brief Determine whether the result should be NaN or Inf based on the sign and mantissa.
 * \param[in] sign: A boolean value representing the sign. If true, it indicates a negative sign; otherwise, a positive sign.
 * \param[in] mant: A 'floatl' type mantissa value used to determine if the result should be NaN.
 * \return A 'floatl' value representing either NaN or Inf with the appropriate sign.
 * 
 * This function first initializes the result as infinity. Then, it checks the mantissa. If the mantissa is non - zero,
 * it returns NaN. Otherwise, it sets the sign bit of the infinity value and returns the result.
 */
static inline floatl floatl_nan_inf(bool sign, floatl mant)
{
    // Initialize the result as infinity
    floatl result = __FLOATL_INF__;
    // Check if the mantissa is non - zero. If so, return NaN
    if (floatl_int_sign(mant))
        return __FLOATL_NAN__;
    // Set the sign bit of the infinity value
    result.u32[__FLOATL_U32_PARTS__ - 1] |= ((uint32_t)sign << 31);
    return result;
}

/**
 * \brief Count the number of leading zero bits in a 32 - bit unsigned integer.
 * \param[in] x: A 32 - bit unsigned integer whose leading zero bits are to be counted.
 * \return The number of leading zero bits in the input 32 - bit unsigned integer.
 * 
 * This function uses a binary search - like approach to count the leading zero bits efficiently.
 * If the input is zero, it immediately returns 32. Otherwise, it narrows down the search range
 * by shifting the number and incrementing a counter accordingly.
 */
static int count_u32_leading_zero(uint32_t x)
{
    // If the input is zero, there are 32 leading zero bits
    if (x == 0)
        return 32;
    int n = 1;
    // Check the higher 16 bits. If they are zero, increment the counter and shift the number
    if ((x >> 16) == 0) { n += 16; x <<= 16; }
    // Check the next 8 bits. If they are zero, increment the counter and shift the number
    if ((x >> 24) == 0) { n += 8; x <<= 8; }
    // Check the next 4 bits. If they are zero, increment the counter and shift the number
    if ((x >> 28) == 0) { n += 4; x <<= 4; }
    // Check the next 2 bits. If they are zero, increment the counter and shift the number
    if ((x >> 30) == 0) { n += 2; x <<= 2; }
    // Adjust the counter based on the most significant bit
    n -= (x >> 31);
    return n;
}

/**
 * \brief Count the total number of leading zero bits in a 'floatl' type value.
 * \param[in] x: A 'floatl' type value whose leading zero bits are to be counted.
 * \return The total number of leading zero bits in the input 'floatl' value.
 * 
 * This function iterates over the 32 - bit parts of the 'floatl' value from the most significant part to the least significant part.
 * If a part is zero, it adds 32 to the counter. If a non - zero part is found, it counts the leading zero bits in that part
 * using the count_u32_leading_zero function and then stops the iteration.
 */
static int count_leading_zero(floatl x)
{
    int n = 0;

    // Iterate over the 32 - bit parts of the 'floatl' value from the most significant part to the least significant part
    for (int i = __FLOATL_U32_PARTS__ - 1; i >= 0; i--) 
    {
        if (x.u32[i] == 0)
        {
            // If the current part is zero, add 32 to the counter
            n += 32;
        }
        else  
        {
            // If the current part is non - zero, count the leading zero bits in this part and break the loop
            n += count_u32_leading_zero(x.u32[i]);
            break;
        }
    }
    return n;
}

/**
 * \brief Perform addition of two 'floatl' numbers by adding their absolute values.
 *        The sign of the result is determined by the sign of the first parameter.
 * \param[in] a: The first 'floatl' number.
 * \param[in] b: The second 'floatl' number.
 * \return A 'floatl' number representing the result of the addition.
 * 
 * This function adds the absolute values of two 'floatl' numbers. It first extracts
 * the exponents and mantissas of the input numbers. Then it handles special cases
 * such as when the exponents are the same, or when one of the numbers is NaN or Inf.
 * After that, it aligns the mantissas according to the exponent difference, adds them,
 * and performs rounding and normalization steps. Finally, it checks for overflow and
 * returns the result with the appropriate sign.
 */
static floatl real_floatl_add(floatl a, floatl b)
{
    // Extract the exponent of the first number
    uint32_t exp1 = a.exponent;
    // Extract the exponent of the second number
    uint32_t exp2 = b.exponent;
    // Extract the mantissa of the first number, setting sign and exponent to 0
    floatl mant1 = a; mant1.sign = 0; mant1.exponent = 0U;
    // Extract the mantissa of the second number, setting sign and exponent to 0
    floatl mant2 = b; mant2.sign = 0; mant2.exponent = 0U;
    // Set the sign of the result to the sign of the first number
    bool sign = a.sign;
    // Calculate the difference between the exponents
    int32_t expdiff = exp1 - exp2;

    // Check if the exponents are the same
    if (expdiff == 0) 
    { 
        // Handle denormalized numbers
        if (exp1 == 0) 
        {
            a = __FLOATL_INT_ZERO__;
            a.sign = sign;
            return a;
        }
        
        // Check for infinity or NaN
        if (exp1 == __FLOATL_ALL_EXP__.exponent)
        {
            return floatl_nan_inf(sign, floatl_int_or(mant1, mant2));
        }
    }

    // Check if the first number is NaN or Inf
    if (exp1 == __FLOATL_ALL_EXP__.exponent) return floatl_nan_inf(sign, mant1);
    // Check if the second number is NaN or Inf
    if (exp2 == __FLOATL_ALL_EXP__.exponent) return floatl_nan_inf(sign, mant2);
        
    // If the first number is denormalized, return the second number with the appropriate sign
    if (exp1 == 0)
    {
        b.sign = sign;
        return b;
    }
        
    // If the second number is denormalized, return the first number with the appropriate sign
    if (exp2 == 0)
    {
        a.sign = sign;
        return a;
    }

    // Add the hidden bit (1) to the mantissas
    mant1 = floatl_int_or(mant1, __FLOATL_HIDE_MANT_BIT__);
    mant2 = floatl_int_or(mant2, __FLOATL_HIDE_MANT_BIT__);

    // Shift the mantissas left by 2 bits
    mant1 = floatl_int_shl(mant1, 2);
    mant2 = floatl_int_shl(mant2, 2);

    // If the exponent of the first number is smaller
    if (expdiff < 0) 
    {
        expdiff = -expdiff;
        // Shift the first mantissa right by the exponent difference, preserving the sticky bit
        mant1 = shift_right_sticky(mant1, expdiff);
        exp1 = exp2;
    }
    // If the exponent of the first number is larger
    else if (expdiff > 0) 
    {
        // Shift the second mantissa right by the exponent difference, preserving the sticky bit
        mant2 = shift_right_sticky(mant2, expdiff);
    }

    // Add the two mantissas
    floatl mant = floatl_int_add(mant1, mant2);

    // Check if the result mantissa is less than the maximum allowed value
    if (floatl_int_ucmp(mant, __FLOATL_MANT_PLUS_MAX__) < 0)
    {
        // Shift the mantissa left by 1 bit
        mant = floatl_int_shl(mant, 1);
    } 
    else  
    {
        // Increment the exponent if the mantissa overflows
        exp1++;
    }
        
    // Perform round - to - even rounding on the mantissa
    mant = round_even_grs(mant);
    // Check if the rounded mantissa exceeds the maximum value
    if (floatl_int_ucmp(mant, __FLOATL_MANT_WHL__) > 0)
    {
        // Increment the exponent if the rounded mantissa overflows
        exp1++;
    }
    
    // Check for overflow of the exponent
    if (exp1 > ((uint32_t)(__FLOATL_ALL_EXP__.exponent) - 1))
    {
        a = __FLOATL_INF__;
        a.sign = sign;
        return a;
    }

    // Set the result number with the new mantissa, sign, and exponent
    a = mant;
    a.sign = sign;
    a.exponent = exp1;

    return a;
}

/**
 * \brief Perform subtraction of two 'floatl' numbers by subtracting their absolute values.
 *        The sign of the result is the sign of the number with the larger absolute value.
 * \param[in] a: The first 'floatl' number.
 * \param[in] b: The second 'floatl' number.
 * \return A 'floatl' number representing the result of the subtraction.
 * 
 * This function subtracts the absolute values of two 'floatl' numbers. It first extracts
 * the exponents and mantissas of the input numbers. Then it handles special cases
 * such as when the exponents are the same, or when one of the numbers is NaN or Inf.
 * After that, it aligns the mantissas according to the exponent difference, subtracts them,
 * and performs normalization and rounding steps. Finally, it checks for underflow and
 * returns the result with the appropriate sign.
 */
static floatl real_floatl_sub(floatl a, floatl b)
{
    // Extract the exponent of the first number
    uint32_t exp1 = a.exponent;
    // Extract the exponent of the second number
    uint32_t exp2 = b.exponent;
    // Extract the mantissa of the first number, setting sign and exponent to 0
    floatl mant1 = a; mant1.sign = 0; mant1.exponent = 0U;
    // Extract the mantissa of the second number, setting sign and exponent to 0
    floatl mant2 = b; mant2.sign = 0; mant2.exponent = 0U;
    // Initialize the result mantissa to zero
    floatl mant = __FLOATL_INT_ZERO__;
    // Set the sign of the result to the sign of the first number
    bool sign = a.sign;
    // Calculate the difference between the exponents
    int32_t expdiff = exp1 - exp2;

    // Check if the exponents are the same
    if (expdiff == 0) 
    {
        // Return NaN if both exponents represent NaN or Inf
        if (exp1 == __FLOATL_ALL_EXP__.exponent) return __FLOATL_NAN__;

        // Return zero if the mantissas are equal
        if (floatl_int_ucmp(mant1, mant2) == 0) return __FLOATL_INT_ZERO__;

        // If the first mantissa is larger
        if (floatl_int_ucmp(mant1, mant2) > 0)
        {
            // Subtract the second mantissa from the first
            mant = floatl_int_sub(mant1, mant2);
        }
        else 
        {
            // Subtract the first mantissa from the second and reverse the sign
            mant = floatl_int_sub(mant2, mant1);
            sign = !sign;
        }
        // Shift the result mantissa left by 3 bits
        mant = floatl_int_shl(mant, 3);
    }
    // If the exponent of the first number is smaller
    else if (expdiff < 0) 
    {
        // Reverse the sign of the result
        sign = !sign;

        // Check if the second number is NaN or Inf
        if (exp2 == __FLOATL_ALL_EXP__.exponent) return floatl_nan_inf(sign, mant2);
        // If the first number is denormalized, return the second number with the appropriate sign
        if (exp1 == 0) { b.sign = sign; return b; }

        exp1 = exp2;
        expdiff = -expdiff;
        // Add the hidden bit to the first mantissa and shift it left by 3 bits
        mant1 = floatl_int_shl(floatl_int_or(mant1, __FLOATL_HIDE_MANT_BIT__), 3);
        // Shift the first mantissa right by the exponent difference, preserving the sticky bit
        mant1 = shift_right_sticky(mant1, expdiff);
        // Add the hidden bit to the second mantissa, shift it left by 3 bits, and subtract the first mantissa
        mant = floatl_int_sub(floatl_int_shl(floatl_int_or(mant2, __FLOATL_HIDE_MANT_BIT__), 3), mant1);
    }
    else 
    {
        // Check if the first number is NaN or Inf
        if (exp1 == __FLOATL_ALL_EXP__.exponent) return floatl_nan_inf(sign, mant1);
        // If the second number is denormalized, return the first number with the appropriate sign
        if (exp2 == 0) { a.sign = sign; return a; }

        // Add the hidden bit to the second mantissa and shift it left by 3 bits
        mant2 = floatl_int_shl(floatl_int_or(mant2, __FLOATL_HIDE_MANT_BIT__), 3);
        // Shift the second mantissa right by the exponent difference, preserving the sticky bit
        mant2 = shift_right_sticky(mant2, expdiff);
        // Add the hidden bit to the first mantissa, shift it left by 3 bits, and subtract the second mantissa
        mant = floatl_int_sub(floatl_int_shl(floatl_int_or(mant1, __FLOATL_HIDE_MANT_BIT__), 3), mant2);
    }

    // Count the leading zero bits in the result mantissa and adjust for the exponent bits
    int shift = count_leading_zero(mant) - (__FLOATL_EXP_BITS__ - 3);
    // Limit the shift to the current exponent value
    if (shift > exp1)
    {
        shift = exp1;
        // Shift the mantissa right by 1 bit
        mant = floatl_int_shr(mant, 1);
    } 
    // Decrease the exponent by the shift amount
    exp1 -= shift;
    // Shift the mantissa left by the shift amount
    mant = floatl_int_shl(mant, shift);

    // Perform round - to - even rounding on the mantissa
    mant = round_even_grs(mant);
    // Check if the rounded mantissa exceeds the maximum value
    if (floatl_int_ucmp(mant, __FLOATL_MANT_WHL__) > 0)
    {
        // Increment the exponent if the rounded mantissa overflows
        exp1++;
    }

    // Check for underflow of the exponent
    if (exp1 < 1)
    {
        a = __FLOATL_INT_ZERO__;
        a.sign = sign;
        return a;
    }

    // Set the result number with the new mantissa, sign, and exponent
    a = mant;
    a.sign = sign;
    a.exponent = exp1;

    return a;
}

/**
 * \brief Perform addition of two 'floatl' numbers.
 * \param[in] a: The first 'floatl' number to be added.
 * \param[in] b: The second 'floatl' number to be added.
 * \return A 'floatl' number representing the result of the addition.
 * 
 * This function decides whether to perform an actual addition or subtraction based on the signs of the two input numbers.
 * If the signs of 'a' and 'b' are the same, it calls the 'real_floatl_add' function to add their absolute values.
 * If the signs are different, it calls the 'real_floatl_sub' function to subtract their absolute values.
 */
floatl floatl_add(floatl a, floatl b)
{
    // Check if the signs of the two numbers are the same
    if (a.sign == b.sign)
        // If the signs are the same, perform addition of absolute values
        return real_floatl_add(a, b);
    // If the signs are different, perform subtraction of absolute values
    return real_floatl_sub(a, b);
}

/**
 * \brief Perform subtraction of two 'floatl' numbers.
 * \param[in] a: The minuend 'floatl' number.
 * \param[in] b: The subtrahend 'floatl' number.
 * \return A 'floatl' number representing the result of the subtraction.
 * 
 * This function determines whether to perform an actual subtraction or addition based on the signs of the two input numbers.
 * If the signs of 'a' and 'b' are the same, it calls the 'real_floatl_sub' function to subtract their absolute values.
 * If the signs are different, it calls the 'real_floatl_add' function to add their absolute values.
 */
floatl floatl_sub(floatl a, floatl b)
{
    // Check if the signs of the two numbers are the same
    if (a.sign == b.sign)
        // If the signs are the same, perform subtraction of absolute values
        return real_floatl_sub(a, b);
    // If the signs are different, perform addition of absolute values
    return real_floatl_add(a, b);
}

/**
 * \brief Perform multiplication of two 'floatl' numbers.
 * \param[in] a: The first 'floatl' number to be multiplied.
 * \param[in] b: The second 'floatl' number to be multiplied.
 * \return A 'floatl' number representing the result of the multiplication.
 * 
 * This function multiplies two 'floatl' numbers 'a' and 'b'. It first extracts the exponents and mantissas
 * of the input numbers. Then it checks for special cases such as infinity, NaN, and zero. After that,
 * it calculates the new exponent and multiplies the mantissas. It performs normalization, rounding,
 * and checks for underflow and overflow conditions. Finally, it returns the result with the appropriate sign.
 */
floatl floatl_mul(floatl a, floatl b)
{
    // Extract the exponent of the first number
    uint32_t exp1 = a.exponent;
    // Extract the exponent of the second number
    uint32_t exp2 = b.exponent;
    // Extract the mantissa of the first number, setting sign and exponent to 0
    floatl mant1 = a; mant1.sign = 0; mant1.exponent = 0U;
    // Extract the mantissa of the second number, setting sign and exponent to 0
    floatl mant2 = b; mant2.sign = 0; mant2.exponent = 0U;
    // Determine the sign of the result using XOR
    bool sign = a.sign ^ b.sign;

    // Check if the first number is infinity or NaN
    if (exp1 == __FLOATL_ALL_EXP__.exponent)
    {
        // Check for NaN conditions
        if (floatl_sign(mant1) || ((exp2 == __FLOATL_ALL_EXP__.exponent) && floatl_sign(mant2)) || (exp2 == 0))
            return __FLOATL_NAN__;

        // Set the result to infinity with the appropriate sign
        a = __FLOATL_INF__;
        a.sign = sign;
        return a;
    }

    // Check if the second number is infinity or NaN
    if (exp2 == __FLOATL_ALL_EXP__.exponent)
    {
        // Check for NaN conditions
        if (floatl_sign(mant2) || (exp1 == 0))
            return __FLOATL_NAN__;

        // Set the result to infinity with the appropriate sign
        a = __FLOATL_INF__;
        a.sign = sign;
        return a;
    }

    // Check if either number is zero
    if ((exp1 == 0) || (exp2 == 0))
    {
        // Set the result to zero with the appropriate sign
        a = __FLOATL_INT_ZERO__;
        a.sign = sign;
        return a;
    }

    // Initialize the result mantissa to zero
    floatl mant = __FLOATL_INT_ZERO__;
    // Calculate the new exponent
    int32_t exp = exp1 + exp2 - __FLOATL_EXP_MID_VALUE__;

    // Add the hidden bit (1) to the mantissas
    mant1 = floatl_int_or(mant1, __FLOATL_HIDE_MANT_BIT__);
    mant2 = floatl_int_or(mant2, __FLOATL_HIDE_MANT_BIT__);

    // Multiply the mantissas and perform right shift with sticky bit preservation
    mant = shift_right_sticky_fl2(mant1, mant2);
    // Check if the result mantissa is less than the maximum allowed value
    if (floatl_int_ucmp(mant, __FLOATL_MANT_PLUS_MAX__) < 0)
    {
        // Shift the mantissa left by 1 bit
        mant = floatl_int_shl(mant, 1);
    }
    else
    {
        // Increment the exponent if the mantissa overflows
        exp++;
    }

    // Perform round - to - even rounding on the mantissa
    mant = round_even_grs(mant);
    // Check if the rounded mantissa exceeds the maximum value
    if (floatl_int_ucmp(mant, __FLOATL_MANT_WHL__) > 0)
        exp++;

    // Check for underflow of the exponent
    if (exp < 1)
    {
        // Set the result to zero with the appropriate sign
        a = __FLOATL_INT_ZERO__;
        a.sign = sign;
        return a;
    }

    // Check for overflow of the exponent
    if (exp > ((uint32_t)__FLOATL_ALL_EXP__.exponent - 1))
    {
        // Set the result to infinity with the appropriate sign
        a = __FLOATL_INF__;
        a.sign = sign;
        return a;
    }

    // Set the result number with the new mantissa, sign, and exponent
    a = mant;
    a.sign = sign;
    a.exponent = exp;

    return a;
}

/**
 * \brief Perform division of two 'floatl' numbers.
 * \param[in] a: The dividend 'floatl' number.
 * \param[in] b: The divisor 'floatl' number.
 * \return A 'floatl' number representing the result of the division.
 * 
 * This function divides two 'floatl' numbers 'a' by 'b'. It first extracts the exponents and mantissas
 * of the input numbers. Then it checks for special cases such as infinity, NaN, and zero. After that,
 * it calculates the new exponent and performs the division of the mantissas. It performs normalization,
 * rounding, and checks for underflow and overflow conditions. Finally, it returns the result with the appropriate sign.
 */
floatl floatl_div(floatl a, floatl b)
{
    // Extract the exponent of the first number
    uint32_t exp1 = a.exponent;
    // Extract the exponent of the second number
    uint32_t exp2 = b.exponent;
    // Extract the mantissa of the first number, setting sign and exponent to 0
    floatl mant1 = a; mant1.sign = 0; mant1.exponent = 0U;
    // Extract the mantissa of the second number, setting sign and exponent to 0
    floatl mant2 = b; mant2.sign = 0; mant2.exponent = 0U;
    // Determine the sign of the result using XOR
    bool sign = a.sign ^ b.sign;

    // Check if the first number is infinity or NaN
    if (exp1 == __FLOATL_ALL_EXP__.exponent)
    {
        // Check for NaN conditions
        if (floatl_int_sign(mant1) || (exp2 == __FLOATL_ALL_EXP__.exponent))
            return __FLOATL_NAN__;

        // Set the result to infinity with the appropriate sign
        a = __FLOATL_INF__;
        a.sign = sign;
        return a;
    }

    // Check if the second number is infinity or NaN
    if (exp2 == __FLOATL_ALL_EXP__.exponent)
    {
        // Check for NaN conditions
        if (floatl_int_sign(mant2))
            return __FLOATL_NAN__;

        // Set the result to zero with the appropriate sign
        a = __FLOATL_INT_ZERO__;
        a.sign = sign;
        return a;
    }

    // Check if the dividend is zero
    if (exp1 == 0) 
    {
        // Check for NaN condition (division of zero by zero)
        if (exp2 == 0)
            return __FLOATL_NAN__;

        // Set the result to zero with the appropriate sign
        a = __FLOATL_INT_ZERO__;
        a.sign = sign;
        return a;
    }

    // Check if the divisor is zero
    if (exp2 == 0)
    {
        // Set the result to infinity with the appropriate sign
        a = __FLOATL_INF__;
        a.sign = sign;
        return a;
    }

    // Calculate the new exponent
    int32_t exp = exp1 - exp2 + __FLOATL_EXP_MID_VALUE__;

    // Add the hidden bit (1) to the mantissas
    mant1 = floatl_int_or(mant1, __FLOATL_HIDE_MANT_BIT__);
    mant2 = floatl_int_or(mant2, __FLOATL_HIDE_MANT_BIT__);

    floatl mant;
    floatl2 sigl2 = FLOATL2(__FLOATL_INT_ZERO__);
    // Check if the dividend mantissa is less than the divisor mantissa
    if (floatl_int_ucmp(mant1, mant2) < 0)
    {
        // Decrease the exponent
        exp--;
        // Shift the dividend mantissa left by __FLOATL_BIT_PARTS__ bits
        sigl2 = floatl2_int_shl(FLOATL2(mant1), __FLOATL_BIT_PARTS__);
    }
    else 
    {
        // Shift the dividend mantissa left by __FLOATL_BIT_PARTS__ - 1 bits
        sigl2 = floatl2_int_shl(FLOATL2(mant1), __FLOATL_BIT_PARTS__ - 1);
    }

    floatl2 rem;
    // Perform the division of the mantissas and shift the result right
    mant = floatl2_int_shr(floatl2_int_udiv(sigl2, FLOATL2(mant2), &rem), __FLOATL_EXP_BITS__ - 3).low;
    // Check if there is a non - zero remainder
    if (floatl_sign(rem.low))
    {
        // Set the least significant bit of the mantissa
        mant.u32[0] |= 1;
    }
    // Perform round - to - even rounding on the mantissa
    mant = round_even_grs(mant);
    // Check for underflow of the exponent
    if (exp < 1)
    {
        // Set the result to zero with the appropriate sign
        a = __FLOATL_INT_ZERO__;
        a.sign = sign;
        return a;
    }

    // Check for overflow of the exponent
    if (exp > ((uint32_t)__FLOATL_ALL_EXP__.exponent - 1))
    {
        // Set the result to infinity with the appropriate sign
        a = __FLOATL_INF__;
        a.sign = sign;
        return a;
    }

    // Set the result number with the new mantissa, sign, and exponent
    a = mant;
    a.sign = sign;
    a.exponent = exp;

    return a;
}

/**
 * \brief Check if the absolute value of the integer part of a 'floatl' number is greater than 1.
 * \param[in] num: The 'floatl' number to be checked.
 * \return 1 if the absolute value of the integer part is greater than 1 (i.e., the integer part is non - zero), 0 otherwise.
 * 
 * This function first checks if the exponent of the 'floatl' number is 1. If so, it returns 0.
 * Then it calculates the actual exponent value by subtracting the mid - value of the exponent range.
 * If the calculated exponent is greater than or equal to 0, it means the integer part is non - zero, and it returns 1.
 */
static int LT1(floatl num)
{
    // If the exponent is 1, the integer part is not greater than 1
    if (((uint32_t)num.exponent) == 1) return 0;
    // Calculate the actual exponent value
    int32_t exp = ((int)num.exponent) - __FLOATL_EXP_MID_VALUE__;
    // Check if the actual exponent is non - negative
    return exp >= 0;
}

/**
 * \brief Check if the absolute value of the fractional part of a 'floatl' number is less than 1.
 * \param[in] num: The 'floatl' number to be checked.
 * \return 1 if the absolute value of the fractional part is less than 1 (i.e., the fractional part is non - zero), 0 otherwise.
 * 
 * This function first calculates the actual exponent value by subtracting the mid - value of the exponent range.
 * If the calculated exponent is negative, it means the fractional part is non - zero, and it returns 1.
 * If the exponent is non - negative and less than the number of mantissa bits, it checks each part of the mantissa
 * to see if there are non - zero bits in the fractional part. If so, it returns 1. Otherwise, it returns 0.
 */
static int ST1(floatl num)
{
    // Calculate the actual exponent value
    int exp = ((int)num.exponent) - __FLOATL_EXP_MID_VALUE__;

    // If the exponent is negative, the fractional part is non - zero
    if (exp < 0) return 1;

    // If the exponent is less than the number of mantissa bits
    if (exp < __FLOATL_MANT_BITS__)
    {
        // Calculate the number of bits in the fractional part
        int bits = __FLOATL_MANT_BITS__ - exp;

        // Iterate over each part of the mantissa
        for (int i = 0; i < __FLOATL_MANT_PARTS__; i++)
        {
            if (bits >= 32)
            {
                // If the number of fractional bits is greater than or equal to 32, check if the current part is non - zero
                if (num.mantissas[i] != 0) return 1;
                // Decrease the number of remaining fractional bits
                bits -= 32;
            }
            else
            {
                // Create a mask to check the fractional bits in the current part
                if ((num.mantissas[i] & ((1 << bits) - 1))) return 1;
                // No more fractional bits to check
                bits = 0;
                break;
            }
        }
        
        // Check the remaining fractional bits in the high - order part of the mantissa
        if (bits && bits <= __FLOATL_MANT_HIGH_BITS__)
        {
            if ((num.mantissa & ((1 << bits) - 1))) return 1;
        }
    }

    return 0;
}

/**
 * \brief Get the character value of the lowest - order digit of the integer part of a 'floatl' number.
 * \param[in] num: The 'floatl' number from which to extract the lowest - order digit of the integer part.
 * \return A character representing the lowest - order digit of the integer part of the 'floatl' number.
 * 
 * This function calculates the lowest - order digit of the integer part of a 'floatl' number.
 * It first calculates the exponent value relative to the mid - value of the exponent range.
 * Then, depending on the exponent value, it either returns '0', '1', or calculates the digit
 * through one of two methods (commented out in the code). The current method involves
 * handling the mantissa parts of the 'floatl' number and performing modular arithmetic
 * to obtain the lowest - order digit.
 */
static char gChar(floatl num)
{
    // An array used to handle the last - digit pattern for powers of 2
    const static char bitEnd[4] = {2,4,8,6};
    // Calculate the actual exponent value
    int32_t exp = ((int)num.exponent) - __FLOATL_EXP_MID_VALUE__;
    uint32_t c = 0;

    // If the exponent is 0, the lowest - order digit of the integer part is 1
    if (exp == 0) return '1';
    // If the exponent is negative, the integer part is 0
    else if (exp < 0) return '0';

#if 1 // This block is commented out. It calculates the result by considering each bit
    // Iterate over each bit of the mantissa
    for (int i = 0; i < __FLOATL_MANT_BITS__; i++)
    {
        // Calculate the position relative to the exponent
        int index = i - __FLOATL_MANT_BITS__ + exp;
        if (index >= 0)
        {
            // Determine the part of the mantissa array and the bit position
            int part = i / 32;
            int bit = i % 32;
            // Get the appropriate part of the mantissa
            uint32_t m = part >= __FLOATL_MANT_PARTS__ ? num.mantissa : num.mantissas[part];
            // Check if the bit is set
            if ((m >> bit) & 1)
            {
                // Add the corresponding value to the accumulator
                c += ((index > 0) ? bitEnd[(index - 1) % 4] : 1);
            }
        }
    }
    // Add the value corresponding to the exponent
    c += ((exp > 0) ? bitEnd[(exp - 1) % 4] : 1);
    // Get the last digit and convert it to a character
    c = c % 10 + '0';
#else // This block is the current method, calculating the result by considering u32 parts
    // Add the hidden bit to the high - order part of the mantissa
    uint32_t hi = (uint32_t)num.mantissa | (1 << __FLOATL_MANT_HIGH_BITS__);

    // If the exponent is less than or equal to the number of high - order mantissa bits
    if (exp <= __FLOATL_MANT_HIGH_BITS__)
    {
        // Calculate the contribution of the high - order mantissa to the last digit
        c += ((hi >> (__FLOATL_MANT_HIGH_BITS__ - exp)) % 10);
    }
    // If the exponent is greater than the number of high - order mantissa bits
    else 
    {
        // Determine the bias based on the exponent
        char bias = bitEnd[(exp - __FLOATL_MANT_HIGH_BITS__ - 1) % 4];
        // Calculate the number of remaining bits
        int bits = exp - __FLOATL_MANT_HIGH_BITS__;

        // Calculate the contribution of the high - order mantissa with the bias
        c += ((hi * bias) % 10);
        // Iterate over the mantissa array parts
        for (int i = __FLOATL_MANT_PARTS__ - 1; i >= 0 && bits > 0; i--, bits -= 32)
        {
            if (bits > 32)
                // Calculate the contribution of the current mantissa part with the bias
                c += ((num.mantissas[i] * bias) % 10);
            else
                // Calculate the contribution of the relevant bits of the current mantissa part
                c += ((num.mantissas[i] >> (32 - bits)) % 10);
        }
    }
    // Get the last digit and convert it to a character
    c = c % 10 + '0';
#endif 

    return (char)c;
}

/**
 * \brief Reverse a string of a specified length.
 * \param[in,out] buffer: A pointer to the character array (string) to be reversed.
 * \param[in] len: The length of the string to be reversed.
 * 
 * This function takes a character array and its length as input. It swaps the characters
 * from the start and the end of the string towards the middle, effectively reversing the string.
 */
static void reverse(char *buffer, int len)
{
    // Iterate over the first half of the string
    for (int i = 0; i < len / 2; i++)
    {
        // Store the current character in a temporary variable
        char tc = buffer[i];
        // Swap the current character with the corresponding character from the end
        buffer[i] = buffer[len - 1 - i];
        buffer[len - 1 - i] = tc;
    }
}

/**
 * \brief Get the decimal character of the lowest - order digit of the integer part of a 'floatl' number
 *        and update the 'floatl' number.
 * \param[in,out] num: A pointer to the 'floatl' number. The number will be updated after the operation.
 * \return The character representing the lowest - order digit of the integer part of the 'floatl' number.
 *         If the integer part is 0, it returns 0.
 * 
 * This function first checks if the integer part of the 'floatl' number is non - zero using the LT1 function.
 * If the integer part is non - zero, it gets the lowest - order digit character using the gChar function.
 * Then it divides the 'floatl' number by 10 to prepare for the next digit extraction.
 */
static char floatlIntLowChar(floatl *num)
{
    char c = 0;
    
    // Check if the integer part of the 'floatl' number is non - zero
    if (LT1(*num)) // >= 1, the integer part is not 0
    {
        // Get the character of the lowest - order digit of the integer part
        c = gChar(*num);
        // Divide the 'floatl' number by 10 to move to the next digit
        *num = floatl_div(*num, floatl_from_d(10.0));
    }

    return c;
}

/**
 * \brief Get the decimal character of the highest - order digit of the fractional part of a 'floatl' number
 *        and update the 'floatl' number.
 * \param[in,out] num: A pointer to the 'floatl' number. The number will be updated after the operation.
 * \return The character representing the highest - order digit of the fractional part of the 'floatl' number.
 *         If the fractional part is 0, it returns 0.
 * 
 * This function first checks if the fractional part of the 'floatl' number is non - zero using the ST1 function.
 * If the fractional part is non - zero, it multiplies the 'floatl' number by 10. Then it gets the highest - order
 * digit character of the new number using the gChar function. Finally, it updates the original 'floatl' number.
 */
static char floatlDitHighChar(floatl *num)
{
    char c = 0;
    floatl temp = *num;

    // Check if the fractional part of the 'floatl' number is non - zero
    if (ST1(temp)) // The decimal part is not 0
    {
        // Multiply the 'floatl' number by 10 to get the next digit
        temp = floatl_mul(temp, floatl_from_d(10.0));
        // Get the character of the highest - order digit of the new number
        c = gChar(temp);
        // Update the original 'floatl' number
        *num = temp;
    }

    return c;
}

/**
 * \brief Perform carry addition on a decimal string.
 * \param[in] begin: A pointer to the start of the string.
 * \param[in] end: A pointer to the end of the string.
 * \param[in] format: A format character used to determine if a specific format marker is reached.
 * \return If an exception occurs, returns a pointer to the abnormal character; if the carry is completed, returns NULL;
 *         if the format marker is reached, returns a pointer to the format marker.
 * 
 * This function traverses the string from the end to the beginning, handling the carry situation of decimal numbers.
 * It skips the decimal point, continues to carry forward when encountering '9', and completes the carry when encountering a space or a valid digit.
 */
static char* floatl_carry_add(char *begin, char *end, char format)
{
    // Start traversing from the end of the string
    char *s = end;
    for (; s >= begin; s--)
    {
        // If the format character is encountered, return a pointer to this character
        if (*s == format) return s;
        // Skip the decimal point
        if (*s == '.') continue; 
        // If the current character is '9', set it to '0' and continue to carry forward
        else if (*s == '9') 
        {
            *s = '0';
            continue;
        }
        // If the current character is a space, set it to '1' to indicate the completion of the carry
        else if (*s == ' ') 
        {
            *s = '1';
            return NULL;
        }
        // If the current character is a digit between '0' and '9', increment it by 1 to complete the carry
        else if (*s >= '0' && *s < '9') 
        {
            (*s)++;
            return NULL;
        }
        // If an abnormal character is encountered, return a pointer to this character
        else return s;
    }

    // If the carry is not completed after traversing the entire string, return s + 1
    return s + 1;
}

/**
 * \brief Perform borrow subtraction on a decimal string.
 * \param[in] begin: A pointer to the start of the string.
 * \param[in] end: A pointer to the end of the string.
 * \param[in] format: A format character used to determine if a specific format marker is reached.
 * \return If an exception occurs, returns a pointer to the abnormal character; if the borrow is completed, returns NULL;
 *         if the format marker is reached, returns a pointer to the format marker.
 * 
 * This function traverses the string from the end to the beginning, handling the borrow situation of decimal numbers.
 * It skips the decimal point, continues to borrow forward when encountering '0', and completes the borrow when encountering a space or a valid digit.
 */
static char* floatl_carry_sub(char *begin, char *end, char format)
{
    // Start traversing from the end of the string
    char *s = end;
    for (; s >= begin; s--)
    {
        // If the format character is encountered, return a pointer to this character
        if (*s == format) return s;
        // Skip the decimal point
        if (*s == '.') continue; 
        // If the current character is '0', set it to '9' and continue to borrow forward
        else if (*s == '0') 
        {
            *s = '9';
            continue;
        }
        // If the current character is a space, set it to '9' to indicate the completion of the borrow
        else if (*s == ' ') 
        {
            *s = '9';
            return NULL;
        }
        // If the current character is a digit between '1' and '9', decrement it by 1 to complete the borrow
        else if (*s > '0' && *s <= '9') 
        {
            (*s)--;
            return NULL;
        }
        // If an abnormal character is encountered, return a pointer to this character
        else return s;
    }

    // If the borrow is not completed after traversing the entire string, return s + 1
    return s + 1;
}

/**
 * \brief Perform carry addition on a hexadecimal string.
 * \param[in] begin: A pointer to the start of the string.
 * \param[in] end: A pointer to the end of the string.
 * \param[in] format: A format character used to control the case of hexadecimal letters.
 * \return If an exception occurs, returns a pointer to the abnormal character; if the carry is completed, returns NULL.
 * 
 * This function traverses the string from the end to the beginning, handling the carry situation of hexadecimal numbers.
 * It skips the decimal point, continues to carry forward when encountering 'F' or 'f', and completes the carry when encountering a space or a valid hexadecimal character.
 */
static char* floatl_carry_add_h(char *begin, char *end, char format)
{
    // Start traversing from the end of the string
    char *s = end;
    for (; s >= begin; s--)
    {
        // Skip the decimal point
        if (*s == '.') continue; 
        // If the current character is 'F' or 'f', set it to '0' and continue to carry forward
        else if (*s == 'F' || *s == 'f') 
        {
            *s = '0';
            continue;
        }
        // If the current character is a space, set it to '1' to indicate the completion of the carry
        else if (*s == ' ') 
        {
            *s = '1';
            return NULL;
        }
        // If the current character is '9', convert it to 'A' or 'a' according to the format
        else if (*s == '9')
        {
            *s = format ? 'A' : 'a';
            return NULL;
        }
        // If the current character is a valid hexadecimal character (digit or letter), increment it by 1 to complete the carry
        else if ((*s >= '0' && *s < '9') ||
                 (*s >= 'A' && *s < 'F') ||
                 (*s >= 'a' && *s < 'f')) 
        {
            (*s)++;
            return NULL;
        }
        // If an abnormal character is encountered, return a pointer to this character
        else return s;
    }

    // If the carry is not completed after traversing the entire string, return s + 1
    return s + 1;
}

/**
 * \brief Extract a 4 - bit hexadecimal digit from the mantissa of a 'floatl' number at a specified index.
 * \param[in] num: The 'floatl' number from which to extract the hexadecimal digit.
 * \param[in] index: The index indicating the position of the 4 - bit group in the mantissa.
 * \return The 4 - bit hexadecimal digit (0 - 15) if valid, - 1 if the index is out of range.
 * 
 * This function extracts a 4 - bit hexadecimal digit from the mantissa of a 'floatl' number at the given index.
 * It first calculates the bit position within the mantissa based on the index. Then it extracts the relevant bits
 * from the appropriate part of the mantissa. If there are insufficient bits in the current part, it may pick up
 * bits from the next part.
 */
static char floatl_mant_hex(floatl num, unsigned int index)
{
    // Calculate the starting bit position of the 4 - bit group
    int bbit = __FLOATL_MANT_BITS__ - 4 - index * 4;
    // Determine the part of the mantissa array where the bit is located
    int part = bbit / 32;
    // Determine the bit position within the part
    int bit = bbit % 32;
    char c = 0;

    // If the bit position is negative, the index is out of range
    if (bbit < 0) return -1;

    if (part < __FLOATL_MANT_PARTS__)
    {
        // Extract the 4 - bit group from the current part of the mantissa
        c = (num.mantissas[part] >> bit) & 0xF;

        /* If there are insufficient bits in the current part, pick up bits from the next part */
        if (bit > 28) 
        {
            if (part == __FLOATL_MANT_PARTS__ - 1) 
                // If it's the last part, pick up bits from the high - order mantissa
                c |= ((num.mantissa << (32 - bit)) & 0xF);
            else    
                // Otherwise, pick up bits from the next part of the mantissa array
                c |= ((num.mantissas[part + 1] << (32 - bit)) & 0xF);
        }
    }
    else 
        // If the bit is in the high - order mantissa, extract it directly
        c = (num.mantissa >> bit) & 0xF;

    return c;
}

/**
 * \brief Convert a 'floatl' number to a string in the %f format.
 * \param[in] num: The 'floatl' number to be converted.
 * \param[out] buffer: A pointer to the character buffer where the converted string will be stored.
 * \param[in] size: The size of the buffer.
 * \param[in] flags: Formatting flags that control the output appearance, such as left - alignment, zero - padding, etc.
 * \param[in] width: The minimum width of the output string.
 * \param[in] precision: The number of digits after the decimal point.
 * \return The length of the converted string.
 * 
 * This function converts a 'floatl' number to a string in the %f format. It first extracts the integer and fractional parts of the number.
 * Then it handles the sign prefix, performs right - or left - alignment based on the flags, and rounds the result if necessary.
 */
static int floatl_convert_f(floatl num, char *buffer, uint32_t size, uint32_t flags, uint32_t width, uint32_t precision)
{
    char c = 0;
    int length = 0;
    // Maximum available space in the buffer (excluding the null terminator)
    uint32_t max = size - 1;
    floatl temp;
    char prefix[2] = {0, 0};
    uint32_t prelen = 0;
    // Length of the fractional part (including the decimal point if precision > 0)
    uint32_t postlen = (precision > 0) ? precision + 1 : 0;

    /* Convert the integer part */
    temp = num;
    // Extract digits of the integer part from the lowest to the highest
    while ((c = floatlIntLowChar(&temp)) > 0) PRINT_CHAR(c);

    /* The integer part is 0 */
    if (length == 0) PRINT_CHAR('0');

    /* Handle the sign prefix */
    if (num.sign) prefix[prelen++] = '-'; // Append negative sign
    else if (flags & FLAGS_PLUS) prefix[prelen++] = '+';

    /* Right - alignment */
    if (!((flags & FLAGS_LEFT)) && (flags & FLAGS_ZEROPAD))
        // Pad with zeros if right - aligned and zero - padding is enabled
        while (length + prelen + postlen < width) PRINT_CHAR('0');
    // Print the sign prefix
    while (prelen > 0) PRINT_CHAR(prefix[--prelen]);
    if (!((flags & FLAGS_LEFT)) && !(flags & FLAGS_ZEROPAD))
        // Pad with spaces if right - aligned and zero - padding is disabled
        while (length + postlen < width) PRINT_CHAR(' ');

    /* Reverse the integer part */
    reverse(buffer, length);

    /* Convert the fractional part */
    if (precision > 0)
    {
        /* Decimal point */
        PRINT_CHAR('.');

        /* Fractional part */
        temp = num;
        // Extract digits of the fractional part from the highest to the lowest
        while (precision && (c = floatlDitHighChar(&temp)) > 0) { PRINT_CHAR(c); precision--; }

        /* Format alignment */
        // Pad with zeros if the fractional part is shorter than the specified precision
        while (precision--) PRINT_CHAR('0');
    }
    else 
    {
        temp = num;
        c = '0';
    }

    /* If the next digit is valid, continue to calculate the next digit */
    if (c > 0)
    {
        c = floatlDitHighChar(&temp);
        if (c >= '5')
        {
            char *begin = buffer;
            char *end = &buffer[length - 1];
            char *move = NULL;
            if (*begin == '+' || *begin == '-') begin++;

            // Perform carry addition for rounding
            move = floatl_carry_add(begin, end, 0);
            if (move)
            {
                if (move > begin)
                {
                    *(move - 1) = *move;
                }
                else 
                {
                    PRINT_CHAR('0');
                    memmove(move + 1, move, end - move + 1);
                }
                *move = '1';
            }
        }
    }

    /* Left - alignment */
    if (flags & FLAGS_LEFT)
        // Pad with spaces if left - aligned
        while (length < width) PRINT_CHAR(' ');
    
    buffer[length] = 0;

    return length;
}

/**
 * \brief Convert a 'floatl' number to a string in the %a format.
 * \param[in] num: The 'floatl' number to be converted.
 * \param[out] buffer: A pointer to the character buffer where the converted string will be stored.
 * \param[in] size: The size of the buffer.
 * \param[in] flags: Formatting flags that control the output appearance, such as case, left - alignment, etc.
 * \param[in] width: The minimum width of the output string.
 * \param[in] precision: The number of hexadecimal digits after the decimal point.
 * \return The length of the converted string, or - 2 if there is not enough space for the exponent part.
 * 
 * This function converts a 'floatl' number to a string in the %a format, which represents the number in hexadecimal
 * floating - point notation. It first converts the exponent part and stores it at the end of the buffer. Then it
 * handles the integer and fractional parts, taking into account formatting flags such as sign, alignment, and case.
 * Finally, it rounds the result if necessary and moves the exponent part to the appropriate position.
 */
static int floatl_convert_a(floatl num, char *buffer, uint32_t size, uint32_t flags, uint32_t width, uint32_t precision)
{
    char c = 0;
    int length = 0;
    // Maximum available space in the buffer (excluding the null terminator)
    uint32_t max = size - 1;
    floatl temp;
    // Pointer to the position where the exponent part will be stored
    char *expBase = buffer + size;
    char prefix[2] = {0, 0};
    uint32_t prelen = 0;
    uint32_t postlen = 0;
    // Calculate the actual exponent value
    int32_t exp = ((int)num.exponent) - __FLOATL_EXP_MID_VALUE__; 
    // Get the hexadecimal digit for rounding
    char carry = floatl_mant_hex(num, precision);

    /* Convert the exponent part and store it at the end of the buffer */
    if (exp == 0) *(--expBase) = '0';
    else
    {
        int32_t texp = exp;
        if (texp < 0) texp = -texp;
        // Convert the exponent to decimal digits and store them in reverse order
        for ( ; texp != 0; texp /= 10)
        {
            c = texp % 10 + '0';
            *(--expBase) = c;
            if (expBase < buffer + 2) return -2;
        }
    }

    /* Calculate the remaining length after the integer part */
    postlen = ((precision > 0) ? precision + 1 : 0) + (buffer + size - expBase) + 2; // .d + p+/- + e

    /* Integer part */
    temp = num;
    if (temp.exponent == 0) PRINT_CHAR('0');
    else PRINT_CHAR('1');
    // Print 'X' or 'x' based on the case flag
    PRINT_CHAR((flags & FLAGS_CASE) ? 'X' : 'x');
    PRINT_CHAR('0');

    /* Handle the sign prefix */
    if (num.sign) prefix[prelen++] = '-'; // Append negative sign
    else if (flags & FLAGS_PLUS) prefix[prelen++] = '+';

    /* Right - alignment */
    if (!((flags & FLAGS_LEFT)) && (flags & FLAGS_ZEROPAD))
        // Pad with zeros if right - aligned and zero - padding is enabled
        while (length + prelen + postlen < width) PRINT_CHAR('0');
    // Print the sign prefix
    while (prelen > 0) PRINT_CHAR(prefix[--prelen]);
    if (!((flags & FLAGS_LEFT)) && !(flags & FLAGS_ZEROPAD))
        // Pad with spaces if right - aligned and zero - padding is disabled
        while (length + postlen < width) PRINT_CHAR(' ');

    /* Reverse the integer part */
    reverse(buffer, length);

    /* Convert the fractional part */
    if (precision > 0)
    {
        /* Decimal point */
        PRINT_CHAR('.');

        /* Fractional part */
        temp = num;
        temp.sign = 0;
        if (floatl_int_cmp(temp, __FLOATL_CONST_0__) == 0)
        {
            PRINT_CHAR('0');
            precision--;
        }
        else 
        {
            int index = 0;
            // Extract and print hexadecimal digits of the fractional part
            while (precision)
            {
                c = floatl_mant_hex(num, index);
                if (c < 0) break;

                if (c < 10) c = c + '0';
                else c = (c - 10) + ((flags & FLAGS_CASE) ? 'A' : 'a');
                PRINT_CHAR(c); 
                
                precision--;
                index++;
            }
        }

        /* Format alignment */
        // Pad with zeros if the fractional part is shorter than the specified precision
        while (precision--) PRINT_CHAR('0');
    }

    // Rounding: If the carry digit is greater than 8, perform carry addition
    if (carry > 8)
    {
        char *begin = buffer;
        char *end = &buffer[length - 1];
        if (*begin == '+' || *begin == '-') begin++;
        floatl_carry_add_h(begin, end, (flags & FLAGS_CASE));
    }

    /* Move the exponent part to the appropriate position */
    // Print 'P' or 'p' based on the case flag
    PRINT_CHAR((flags & FLAGS_CASE) ? 'P' : 'p');
    // Print the sign of the exponent
    PRINT_CHAR(exp < 0 ? '-' : '+');
    // Print the exponent digits
    while (expBase < buffer + size) PRINT_CHAR(*(expBase++));

    /* Left - alignment */
    if (flags & FLAGS_LEFT)
        // Pad with spaces if left - aligned
        while (length < width) PRINT_CHAR(' ');
    
    buffer[length] = 0;

    return length;
}

/**
 * \brief Convert a 'floatl' number to a string in the %e format.
 * \param[in] num: The 'floatl' number to be converted.
 * \param[out] buffer: A pointer to the character buffer where the converted string will be stored.
 * \param[in] size: The size of the buffer.
 * \param[in] flags: Formatting flags that control the output appearance, such as case, left - alignment, etc.
 * \param[in] width: The minimum width of the output string.
 * \param[in] precision: The number of digits after the decimal point.
 * \return The length of the converted string, or - 2 if there is not enough space for the exponent part.
 * 
 * This function converts a 'floatl' number to a string in the %e format, which represents the number in scientific notation.
 * It first extracts the integer and fractional parts of the number, calculates the exponent, and stores the exponent digits at the end of the buffer.
 * Then it handles the sign prefix, performs right - or left - alignment based on the flags, and rounds the result if necessary.
 */
static int floatl_convert_e(floatl num, char *buffer, uint32_t size, uint32_t flags, uint32_t width, uint32_t precision)
{
    char c = 0;
    int length = 0;
    // Maximum available space in the buffer (excluding the null terminator)
    uint32_t max = size - 1;
    floatl temp;
    // Pointer to the position where the exponent part will be stored
    char *expBase = buffer + size;
    char prefix[2] = {0, 0};
    uint32_t prelen = 0;
    uint32_t postlen = 0;
    int offset = 0;
    int32_t exp = 0;
    char *point = NULL;

    // Buffer to store digits, with extra space for integer and precision digits
    char buf[precision + 2]; 
    FL_STACK dstack = {buf, sizeof(buf), 0, 0};

    /* Convert the integer part and push digits onto the stack */
    temp = num;
    while ((c = floatlIntLowChar(&temp)) > 0)
    {
        fl_stack_push(&dstack, c);
        offset++;
    }

    /* Calculate the exponent of the number */
    temp = num;
    if (offset > 0)
    {
        // If there are integer digits, process the fractional part and set the exponent
        while ((c = floatlDitHighChar(&temp)) > 0) fl_stack_push_h(&dstack, c);
        exp = offset - 1;
    }
    else
    {
        if (num.exponent == 0) exp = 0;
        else 
        {
            // If there are no integer digits, find the first non - zero fractional digit and set the exponent
            while ((c = floatlDitHighChar(&temp)) > 0) 
            {
                offset++;

                if (c != '0')
                {
                    fl_stack_push_h(&dstack, c);
                    while (dstack.size < dstack.capacity && (c = floatlDitHighChar(&temp)) > 0) fl_stack_push_h(&dstack, c);
                    exp = -offset;
                    break;
                }
            }
        }
    }
    // Pad the stack with zeros if necessary
    while (dstack.size < dstack.capacity) fl_stack_push_h(&dstack, '0');

    // Pop the first digit and print it
    fl_stack_pop(&dstack, &c);
    PRINT_CHAR(c);

    /* Convert the exponent part and store it at the end of the buffer */
    if (exp == 0) *(--expBase) = '0';
    else
    {
        int32_t texp = exp;
        if (texp < 0) texp = -texp;
        // Convert the exponent to decimal digits and store them in reverse order
        for ( ; texp != 0; texp /= 10)
        {
            c = texp % 10 + '0';
            *(--expBase) = c;
            if (expBase < buffer + 2) return -2;
        }
    }
    // Ensure the exponent part has at least three digits
    while (buffer + size - expBase < 3) *(--expBase) = '0'; 

    /* Calculate the remaining length after the integer part */
    postlen = ((precision > 0) ? precision + 1 : 0) + (buffer + size - expBase) + 2; // .d + e+/- + e

    /* Handle the sign prefix */
    if (num.sign) prefix[prelen++] = '-'; // Append negative sign
    else if (flags & FLAGS_PLUS) prefix[prelen++] = '+';

    /* Right - alignment */
    if (!((flags & FLAGS_LEFT)) && (flags & FLAGS_ZEROPAD))
        // Pad with zeros if right - aligned and zero - padding is enabled
        while (length + prelen + postlen < width) PRINT_CHAR('0');
    // Print the sign prefix
    while (prelen > 0) PRINT_CHAR(prefix[--prelen]);
    if (!((flags & FLAGS_LEFT)) && !(flags & FLAGS_ZEROPAD))
        // Pad with spaces if right - aligned and zero - padding is disabled
        while (length + postlen < width) PRINT_CHAR(' ');

    /* Reverse the integer part */
    reverse(buffer, length);

    if (precision > 0)
    {
        /* Decimal point */
        PRINT_CHAR('.');
        point = &buffer[length - 1];

        // Pop digits from the stack and print them as the fractional part
        while (precision && fl_stack_pop(&dstack, &c)) { PRINT_CHAR(c); precision--; }
    }

    /* Check if rounding is needed */
    if (dstack.size > 0)
    {
        fl_stack_pop(&dstack, &c);

        // If the next digit is 5 or greater, perform rounding
        if (c >= '5')
        {
            char *move = NULL;
            
            // Determine if a carry is needed in the fractional part
            if (point) 
            {
                if (floatl_carry_add(point + 1, &buffer[length - 1], '.')) move = point - 1;
            }
            else move = &buffer[length - 1];

            // If a carry is needed in the integer part
            if (move)
            {
                // If the integer digit can be incremented
                if (*move >= '0' && *move < '9') (*move)++;
                // If the integer digit is 9 and needs to be carried over
                else 
                {
                    // Set the integer digit to 1
                    *move = '1';

                    // Increment the exponent part
                    if (exp >= 0) move = floatl_carry_add(expBase, buffer + size - 1, 0);
                    else          move = floatl_carry_sub(expBase, buffer + size - 1, 0);

                    // If the exponent part needs to be carried over
                    if (move)
                    {
                        if (move <= (buffer + length + 2)) return -2;
                        *(--expBase) = '1';
                    }

                    // Increment the exponent value
                    exp++;
                }
            }
        }
    }

    /* Move the exponent part to the appropriate position */
    // Print 'E' or 'e' based on the case flag
    PRINT_CHAR((flags & FLAGS_CASE) ? 'E' : 'e');
    // Print the sign of the exponent
    PRINT_CHAR(exp < 0 ? '-' : '+');
    // Print the exponent digits
    while (expBase < buffer + size) PRINT_CHAR(*(expBase++));

    /* Left - alignment */
    if (flags & FLAGS_LEFT)
        // Pad with spaces if left - aligned
        while (length < width) PRINT_CHAR(' ');

    buffer[length] = 0;

    return length;
}

/** 
 * \brief Converts a 'floatl' number to a string.
 * 
 * This function takes a 'floatl' number and converts it into a string representation
 * according to a printf-like format string. The resulting string is stored in the provided buffer.
 * 
 * \param[in] a: The 'floatl' number to be converted.
 * \param[out] buffer: A pointer to the buffer where the resulting string will be stored.
 *                     The buffer should be large enough to hold the entire string representation.
 * \param[in] size: The size of the buffer, indicating the maximum number of characters it can hold.
 * \param[in] format: A printf-like format string, structured as [flags][width][type].
 *                    Flags can be '0' (zero-padding), '-' (left-alignment), '+' (force sign),
 *                    ' ' (space for positive numbers), '#' (alternate form).
 *                    Width is a decimal number specifying the minimum width of the output.
 *                    Type can be 'a' 'A' 'e' 'E' 'f' 'F' 'g' 'G', determining the output format.
 * \return The length of the successfully converted string.
 *         Returns 0 if the conversion is invalid.
 *         Returns -1 if the 'buffer' pointer is NULL.
 *         Returns -2 if the 'size' of the buffer is too small.
 *         Returns -3 if the 'format' pointer is NULL.
 */
int floatl_print(floatl a, char *buffer, uint32_t size, const char *format)
{
    int length = 0;
    // Flags used to control the formatting options of the output
    uint32_t flags = 0;
    // Minimum width of the output string
    uint32_t width = 0;
    // Number of digits after the decimal point, default value is 6
    uint32_t precision = 6;
    // Maximum available space in the buffer, excluding the null terminator
    uint32_t max = size - 1;

    // Check if the buffer pointer is NULL. If so, return -1 indicating an error.
    if (!buffer) return -1;
    // Check if the buffer size is less than 2. If so, return -2 as it's too small to hold a valid string.
    if (size < 2) return -2;
    // Check if the format pointer is NULL. If so, return -3 indicating an error.
    if (!format) return -3;

    // Skip the '%' character if it's the first character in the format string.
    if (*format == '%') format++;

    // Parse the format string character by character
    for (; *format; format++)
    {
        // If the length of the converted string is already greater than 0, break the loop.
        if (length > 0) break;

        // Parse the formatting flags in the format string
        while (1)
        {
            if (*format == '0')
            {
                // Set the zero-padding flag
                flags |= FLAGS_ZEROPAD;
                format++;
            }
            else if (*format == '-')
            {
                // Set the left-alignment flag
                flags |= FLAGS_LEFT;
                format++;
            }
            else if (*format == '+')
            {
                // Set the force sign flag
                flags |= FLAGS_PLUS;
                format++;
            }
            else if (*format == ' ')
            {
                // Set the space for positive numbers flag
                flags |= FLAGS_SPACE;
                format++;
            }
            else if (*format == '#')
            {
                // Set the alternate form flag
                flags |= FLAGS_HASH;
                format++;
            }
            else
            {
                // Exit the loop if no more flags are found
                break;
            }
        }

        /* Convert the width specified in the format string */
        // Parse the characters representing the width in the format string
        while ((*format >= '0') && (*format <= '9'))
        {
            // Convert the digit characters to an integer and update the width value
            width = width * 10U + (unsigned int)(*format++ - '0');
        }
        // Check if the specified width exceeds the available buffer space. If so, return -1.
        if (width > max) return -1;

        // Check if the precision is specified in the format string
        if (*format == '.')
        {
            // Reset the precision value
            precision = 0;
            format++;
            // Parse the characters representing the precision in the format string
            while ((*format >= '0') && (*format <= '9'))
            {
                // Convert the digit characters to an integer and update the precision value
                precision = precision * 10U + (unsigned int)(*format++ - '0');
            }
        }
        // Check if the specified precision exceeds the available buffer space (minus 2 for possible sign and decimal point). If so, return -1.
        if (precision > max - 2) return -1;

        /* Distribute the format based on the type specifier */
        // Determine the appropriate conversion function according to the type specifier in the format string
        switch (*format)
        {
        case 'A':
            // Set the case flag for uppercase output
            flags |= FLAGS_CASE;
        case 'a': // Floating-point number in hexadecimal and [P-] notation
        {
            // Call the function to convert the number to hexadecimal floating-point format
            length = floatl_convert_a(a, buffer, size, flags, width, precision);
        }
        break;
        case 'E':
            // Set the case flag for uppercase output
            flags |= FLAGS_CASE;
        case 'e': // Floating-point number in exponential [e-] notation
        {
            // Call the function to convert the number to exponential floating-point format
            length = floatl_convert_e(a, buffer, size, flags, width, precision);
        }
        break;
        case 'G':
        case 'g': // Floating-point number, without displaying meaningless zeros
        case 'F':
        case 'f': // Floating-point number
        {
            // Call the function to convert the number to regular floating-point format
            length = floatl_convert_f(a, buffer, size, flags, width, precision);
        }
        break;
        default:
            // Return 0 if the type specifier is invalid
            return 0;
        }
    }

    // Add a null terminator to the end of the converted string
    buffer[length] = 0;

    // Return the length of the converted string
    return length;
}
